Generator now has module support
This commit is contained in:
parent
2f2e762d02
commit
306b029951
|
@ -84,7 +84,7 @@ func (this *generator) generateAssignmentToDestination ( // TODO: add -Val suffi
|
||||||
sourceDataLoc := this.blockManager.NewLoad(new(llvm.TypePointer), source)
|
sourceDataLoc := this.blockManager.NewLoad(new(llvm.TypePointer), source)
|
||||||
this.blockManager.NewStore(sourceDataLoc, destDataFieldLoc)
|
this.blockManager.NewStore(sourceDataLoc, destDataFieldLoc)
|
||||||
|
|
||||||
fromReferenced, ok := sourceTypeBase.Referenced.(*entity.TypeNamed)
|
sourceType, ok := sourceTypeBase.Referenced.(*entity.TypeNamed)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New(fmt.Sprint(
|
return nil, errors.New(fmt.Sprint(
|
||||||
"can't assign", sourceTypeBase, "to interface"))
|
"can't assign", sourceTypeBase, "to interface"))
|
||||||
|
@ -95,7 +95,12 @@ func (this *generator) generateAssignmentToDestination ( // TODO: add -Val suffi
|
||||||
toBehaviorFieldAddress := this.getInterfaceBehaviorFieldLoc (
|
toBehaviorFieldAddress := this.getInterfaceBehaviorFieldLoc (
|
||||||
destTypeBase, irDestLoc,
|
destTypeBase, irDestLoc,
|
||||||
irDestType, name)
|
irDestType, name)
|
||||||
fromBehavior, err := this.method(fromReferenced.Name, name)
|
key := entity.Key {
|
||||||
|
Unit: sourceType.Unit(),
|
||||||
|
Name: sourceType.Name,
|
||||||
|
Method: name,
|
||||||
|
}
|
||||||
|
fromBehavior, err := this.method(key)
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
this.blockManager.NewStore(fromBehavior, toBehaviorFieldAddress)
|
this.blockManager.NewStore(fromBehavior, toBehaviorFieldAddress)
|
||||||
}
|
}
|
||||||
|
@ -118,7 +123,12 @@ func (this *generator) generateAssignmentToDestination ( // TODO: add -Val suffi
|
||||||
toBehaviorFieldAddress := this.getInterfaceBehaviorFieldLoc (
|
toBehaviorFieldAddress := this.getInterfaceBehaviorFieldLoc (
|
||||||
destTypeBase, irDestLoc,
|
destTypeBase, irDestLoc,
|
||||||
irDestType, name)
|
irDestType, name)
|
||||||
fromBehavior, err := this.method(sourceType.Name, name)
|
key := entity.Key {
|
||||||
|
Unit: sourceType.Unit(),
|
||||||
|
Name: sourceType.Name,
|
||||||
|
Method: name,
|
||||||
|
}
|
||||||
|
fromBehavior, err := this.method(key)
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
this.blockManager.NewStore(fromBehavior, toBehaviorFieldAddress)
|
this.blockManager.NewStore(fromBehavior, toBehaviorFieldAddress)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,11 @@ func (this *generator) generateDeclarationLoc (declaration *entity.Declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *generator) generateSliceLoc (slice *entity.Slice) (llvm.Value, error) {
|
func (this *generator) generateSliceLoc (slice *entity.Slice) (llvm.Value, error) {
|
||||||
var err error
|
|
||||||
var start, end, dataAddress llvm.Value
|
var start, end, dataAddress llvm.Value
|
||||||
var elementType llvm.Type
|
var elementType llvm.Type
|
||||||
var sizeType *llvm.TypeInt; {
|
|
||||||
ty, err := this.typedef("Index")
|
sizeType, err := this.generateTypeIndex()
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
sizeType = ty.(*llvm.TypeInt)
|
|
||||||
}
|
|
||||||
|
|
||||||
if slice.Start != nil {
|
if slice.Start != nil {
|
||||||
start, err = this.generateExpressionVal(slice.Start)
|
start, err = this.generateExpressionVal(slice.Start)
|
||||||
|
|
|
@ -7,7 +7,10 @@ import "git.tebibyte.media/sashakoshka/fspl/entity"
|
||||||
import "git.tebibyte.media/sashakoshka/fspl/analyzer"
|
import "git.tebibyte.media/sashakoshka/fspl/analyzer"
|
||||||
|
|
||||||
func (this *generator) generateCallVal (call *entity.Call) (llvm.Value, error) {
|
func (this *generator) generateCallVal (call *entity.Call) (llvm.Value, error) {
|
||||||
function, err := this.function(call.Name)
|
function, err := this.function(entity.Key {
|
||||||
|
Unit: call.Unit,
|
||||||
|
Name: call.Name,
|
||||||
|
})
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
|
|
||||||
args := make([]llvm.Value, len(call.Arguments))
|
args := make([]llvm.Value, len(call.Arguments))
|
||||||
|
@ -41,7 +44,11 @@ func (this *generator) generateMethodCallVal (call *entity.MethodCall) (llvm.Val
|
||||||
|
|
||||||
// check for methods on named type
|
// check for methods on named type
|
||||||
if sourceType, ok := call.Source.Type().(*entity.TypeNamed); ok {
|
if sourceType, ok := call.Source.Type().(*entity.TypeNamed); ok {
|
||||||
method, err := this.method(sourceType.Name, call.Name)
|
method, err := this.method(entity.Key {
|
||||||
|
Unit: sourceType.Unit(),
|
||||||
|
Name: sourceType.Name,
|
||||||
|
Method: call.Name,
|
||||||
|
})
|
||||||
if err != errNotFound {
|
if err != errNotFound {
|
||||||
source, err := this.generateExpressionLoc(call.Source)
|
source, err := this.generateExpressionLoc(call.Source)
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
|
@ -53,7 +60,11 @@ func (this *generator) generateMethodCallVal (call *entity.MethodCall) (llvm.Val
|
||||||
// check for methods on pointer to named type
|
// check for methods on pointer to named type
|
||||||
if pointerType, ok := call.Source.Type().(*entity.TypePointer); ok {
|
if pointerType, ok := call.Source.Type().(*entity.TypePointer); ok {
|
||||||
if sourceType, ok := pointerType.Referenced.(*entity.TypeNamed); ok {
|
if sourceType, ok := pointerType.Referenced.(*entity.TypeNamed); ok {
|
||||||
method, err := this.method(sourceType.Name, call.Name)
|
method, err := this.method(entity.Key {
|
||||||
|
Unit: sourceType.Unit(),
|
||||||
|
Name: sourceType.Name,
|
||||||
|
Method: call.Name,
|
||||||
|
})
|
||||||
if err != errNotFound {
|
if err != errNotFound {
|
||||||
source, err := this.generateExpressionVal(call.Source)
|
source, err := this.generateExpressionVal(call.Source)
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
|
@ -93,11 +104,8 @@ func (this *generator) generateReferenceVal (reference *entity.Reference) (llvm.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *generator) generateLengthVal (length *entity.Length) (llvm.Value, error) {
|
func (this *generator) generateLengthVal (length *entity.Length) (llvm.Value, error) {
|
||||||
var sizeType *llvm.TypeInt; {
|
sizeType, err := this.generateTypeIndex()
|
||||||
ty, err := this.typedef("Index")
|
if err != nil { return nil, err }
|
||||||
if err != nil { return nil, err }
|
|
||||||
sizeType = ty.(*llvm.TypeInt)
|
|
||||||
}
|
|
||||||
|
|
||||||
source, err := this.generateExpressionLoc(length.Slice)
|
source, err := this.generateExpressionLoc(length.Slice)
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
|
|
|
@ -9,6 +9,11 @@ func (this *generator) generateFunction (
|
||||||
*llvm.Function,
|
*llvm.Function,
|
||||||
error,
|
error,
|
||||||
) {
|
) {
|
||||||
|
key := entity.Key {
|
||||||
|
Unit: function.Unit,
|
||||||
|
Name: function.Signature.Name,
|
||||||
|
}
|
||||||
|
|
||||||
params := make([]*llvm.Parameter, len(function.Signature.Arguments))
|
params := make([]*llvm.Parameter, len(function.Signature.Arguments))
|
||||||
|
|
||||||
ret, err := this.generateType(function.Signature.Return)
|
ret, err := this.generateType(function.Signature.Return)
|
||||||
|
@ -21,7 +26,7 @@ func (this *generator) generateFunction (
|
||||||
}
|
}
|
||||||
|
|
||||||
var name string; if function.LinkName == "" {
|
var name string; if function.LinkName == "" {
|
||||||
name = function.Signature.Name
|
name = key.LinkName()
|
||||||
} else {
|
} else {
|
||||||
name = function.LinkName
|
name = function.LinkName
|
||||||
}
|
}
|
||||||
|
@ -44,7 +49,7 @@ func (this *generator) generateFunction (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.functions[function.Signature.Name] = irFunc
|
this.functions[key] = irFunc
|
||||||
return irFunc, nil
|
return irFunc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +59,12 @@ func (this *generator) generateMethod (
|
||||||
*llvm.Function,
|
*llvm.Function,
|
||||||
error,
|
error,
|
||||||
) {
|
) {
|
||||||
|
key := entity.Key {
|
||||||
|
Unit: method.Unit,
|
||||||
|
Name: method.TypeName,
|
||||||
|
Method: method.Signature.Name,
|
||||||
|
}
|
||||||
|
|
||||||
params := make([]*llvm.Parameter, len(method.Signature.Arguments) + 1)
|
params := make([]*llvm.Parameter, len(method.Signature.Arguments) + 1)
|
||||||
|
|
||||||
ret, err := this.generateType(method.Signature.Return)
|
ret, err := this.generateType(method.Signature.Return)
|
||||||
|
@ -67,7 +78,7 @@ func (this *generator) generateMethod (
|
||||||
params[0] = llvm.NewParameter("this", new(llvm.TypePointer))
|
params[0] = llvm.NewParameter("this", new(llvm.TypePointer))
|
||||||
|
|
||||||
var name string; if method.LinkName == "" {
|
var name string; if method.LinkName == "" {
|
||||||
name = method.TypeName + "." + method.Signature.Name
|
name = key.LinkName()
|
||||||
} else {
|
} else {
|
||||||
name = method.LinkName
|
name = method.LinkName
|
||||||
}
|
}
|
||||||
|
@ -90,6 +101,6 @@ func (this *generator) generateMethod (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.functions[method.TypeName + "." + method.Signature.Name] = irFunc
|
this.functions[key] = irFunc
|
||||||
return irFunc, nil
|
return irFunc, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package generator
|
||||||
import "sort"
|
import "sort"
|
||||||
import "errors"
|
import "errors"
|
||||||
import "git.tebibyte.media/sashakoshka/fspl/llvm"
|
import "git.tebibyte.media/sashakoshka/fspl/llvm"
|
||||||
|
import "git.tebibyte.media/sashakoshka/fspl/entity"
|
||||||
import "git.tebibyte.media/sashakoshka/fspl/analyzer"
|
import "git.tebibyte.media/sashakoshka/fspl/analyzer"
|
||||||
|
|
||||||
var errNotFound = errors.New("entity not found")
|
var errNotFound = errors.New("entity not found")
|
||||||
|
@ -22,7 +23,8 @@ type generator struct {
|
||||||
tree analyzer.Tree
|
tree analyzer.Tree
|
||||||
module *llvm.Module
|
module *llvm.Module
|
||||||
|
|
||||||
functions map[string] *llvm.Function
|
types map[entity.Key] llvm.Type
|
||||||
|
functions map[entity.Key] *llvm.Function
|
||||||
|
|
||||||
managerStack []*blockManager
|
managerStack []*blockManager
|
||||||
blockManager *blockManager
|
blockManager *blockManager
|
||||||
|
@ -36,25 +38,28 @@ func (this Target) Generate (tree analyzer.Tree) (*llvm.Module, error) {
|
||||||
module: new(llvm.Module),
|
module: new(llvm.Module),
|
||||||
target: this,
|
target: this,
|
||||||
tree: tree,
|
tree: tree,
|
||||||
functions: make(map[string] *llvm.Function),
|
types: make(map[entity.Key] llvm.Type),
|
||||||
|
functions: make(map[entity.Key] *llvm.Function),
|
||||||
}).generate()
|
}).generate()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *generator) generate () (*llvm.Module, error) {
|
func (this *generator) generate () (*llvm.Module, error) {
|
||||||
// generate functions
|
// generate functions
|
||||||
functions := sortMapKeys(this.tree.Functions)
|
functions := sortKeyedMapKeys(this.tree.Functions)
|
||||||
for _, functionName := range functions {
|
for _, key := range functions {
|
||||||
_, err := this.function(functionName)
|
_, err := this.function(key)
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate methods
|
// generate methods
|
||||||
types := sortMapKeys(this.tree.Types)
|
types := sortKeyedMapKeys(this.tree.Types)
|
||||||
for _, typeName := range types {
|
for _, key := range types {
|
||||||
ty := this.tree.Types[typeName]
|
ty := this.tree.Types[key]
|
||||||
methods := sortMapKeys(ty.Methods)
|
methods := sortMapKeys(ty.Methods)
|
||||||
for _, methodName := range methods {
|
for _, methodName := range methods {
|
||||||
_, err := this.method(typeName, methodName)
|
methodKey := key
|
||||||
|
methodKey.Method = methodName
|
||||||
|
_, err := this.method(methodKey)
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,39 +67,37 @@ func (this *generator) generate () (*llvm.Module, error) {
|
||||||
return this.module, nil
|
return this.module, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *generator) typedef (typeName string) (llvm.Type, error) {
|
func (this *generator) typedef (key entity.Key) (llvm.Type, error) {
|
||||||
for _, ty := range this.module.Types {
|
ty, exists := this.types[key]
|
||||||
if ty.Name() == typeName {
|
if exists { return ty, nil }
|
||||||
return ty, nil
|
|
||||||
}
|
def, exists := this.tree.Types[key]
|
||||||
}
|
|
||||||
def, exists := this.tree.Types[typeName]
|
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, errNotFound
|
return nil, errNotFound
|
||||||
}
|
}
|
||||||
return this.generateTypedef(def)
|
return this.generateTypedef(def)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *generator) method (typeName string, name string) (*llvm.Function, error) {
|
func (this *generator) method (key entity.Key) (*llvm.Function, error) {
|
||||||
method, exists := this.functions[typeName + "." + name]
|
method, exists := this.functions[key]
|
||||||
if exists { return method, nil }
|
if exists { return method, nil }
|
||||||
|
|
||||||
ty, exists := this.tree.Types[typeName]
|
ty, exists := this.tree.Types[key.StripMethod()]
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, errNotFound
|
return nil, errNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
if method, exists := ty.Methods[name]; exists {
|
if method, exists := ty.Methods[key.Method]; exists {
|
||||||
return this.generateMethod(method)
|
return this.generateMethod(method)
|
||||||
}
|
}
|
||||||
return nil, errNotFound
|
return nil, errNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *generator) function (name string) (*llvm.Function, error) {
|
func (this *generator) function (key entity.Key) (*llvm.Function, error) {
|
||||||
function, exists := this.functions[name]
|
function, exists := this.functions[key]
|
||||||
if exists { return function, nil }
|
if exists { return function, nil }
|
||||||
|
|
||||||
if function, exists := this.tree.Functions[name]; exists {
|
if function, exists := this.tree.Functions[key]; exists {
|
||||||
return this.generateFunction(function)
|
return this.generateFunction(function)
|
||||||
}
|
}
|
||||||
return nil, errNotFound
|
return nil, errNotFound
|
||||||
|
@ -110,3 +113,36 @@ func sortMapKeys[T any] (unsorted map[string] T) []string {
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type keySlice []entity.Key
|
||||||
|
|
||||||
|
func (keys keySlice) Len () int {
|
||||||
|
return len(keys)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (keys keySlice) Less (lefti, righti int) bool {
|
||||||
|
left := keys[lefti]
|
||||||
|
right := keys[righti]
|
||||||
|
|
||||||
|
for index, leftByte := range left.Unit {
|
||||||
|
if right.Unit[index] <= leftByte {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return left.Name < right.Name && left.Method < right.Method
|
||||||
|
}
|
||||||
|
|
||||||
|
func (keys keySlice) Swap (lefti, righti int) {
|
||||||
|
keys[lefti], keys[righti] = keys[righti], keys[lefti]
|
||||||
|
}
|
||||||
|
|
||||||
|
func sortKeyedMapKeys[T any] (unsorted map[entity.Key] T) keySlice {
|
||||||
|
keys := make(keySlice, len(unsorted))
|
||||||
|
index := 0
|
||||||
|
for key := range unsorted {
|
||||||
|
keys[index] = key
|
||||||
|
index ++
|
||||||
|
}
|
||||||
|
sort.Sort(keys)
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
|
@ -1,33 +1,78 @@
|
||||||
package generator
|
package generator
|
||||||
|
|
||||||
import "io"
|
|
||||||
import "testing"
|
import "testing"
|
||||||
import "strings"
|
import "strings"
|
||||||
|
import "github.com/google/uuid"
|
||||||
import "git.tebibyte.media/sashakoshka/fspl/lexer"
|
import "git.tebibyte.media/sashakoshka/fspl/lexer"
|
||||||
|
import "git.tebibyte.media/sashakoshka/fspl/errors"
|
||||||
|
import "git.tebibyte.media/sashakoshka/fspl/entity"
|
||||||
import "git.tebibyte.media/sashakoshka/fspl/analyzer"
|
import "git.tebibyte.media/sashakoshka/fspl/analyzer"
|
||||||
import "git.tebibyte.media/sashakoshka/fspl/testcommon"
|
import "git.tebibyte.media/sashakoshka/fspl/testcommon"
|
||||||
import "git.tebibyte.media/sashakoshka/fspl/parser/fspl"
|
import "git.tebibyte.media/sashakoshka/fspl/parser/fspl"
|
||||||
|
|
||||||
func testString (test *testing.T, correct string, input string) {
|
func testString (test *testing.T, correct string, input string) {
|
||||||
ast := fsplParser.Tree { }
|
address := entity.Address("main.fspl")
|
||||||
lx, err := lexer.LexReader("input.fspl", strings.NewReader(input))
|
ast, ok := treeOf(test, address, input, false)
|
||||||
if err != nil {
|
if !ok { return }
|
||||||
test.Error("lexer returned error:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = ast.Parse(fsplParser.UnitInfo { }, lx)
|
|
||||||
if err != nil && err != io.EOF{
|
|
||||||
test.Error("parser returned error:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tree := analyzer.Tree { }
|
tree := analyzer.Tree { }
|
||||||
err = tree.Analyze(ast)
|
err := tree.Analyze(address.UUID(), nil, ast)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
test.Error("analyzer returned error:", err)
|
test.Error("analyzer returned error:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testSemanticTree(test, correct, input, tree)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUnits (
|
||||||
|
test *testing.T,
|
||||||
|
correct string,
|
||||||
|
main string,
|
||||||
|
dependencies ...string,
|
||||||
|
) {
|
||||||
|
if len(dependencies) % 2 != 0 {
|
||||||
|
panic("dependencies len must be even. forget an address?")
|
||||||
|
}
|
||||||
|
tree := analyzer.Tree { }
|
||||||
|
nicknames := make(map[string] uuid.UUID)
|
||||||
|
|
||||||
|
// dependencies
|
||||||
|
for index := 0; index < len(dependencies) - 1; index += 2 {
|
||||||
|
address := entity.Address(dependencies[index])
|
||||||
|
source := dependencies[index + 1]
|
||||||
|
ast, ok := treeOf(test, address, source, true)
|
||||||
|
if !ok { return }
|
||||||
|
|
||||||
|
err := tree.Analyze(address.UUID(), nicknames, ast)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("analyzer returned error:\n" + errors.Format(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
unit := address.UUID()
|
||||||
|
nickname, ok := address.Nickname()
|
||||||
|
if !ok {
|
||||||
|
test.Errorf("could not generate nickname for %v", address)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
nicknames[nickname] = unit
|
||||||
|
}
|
||||||
|
|
||||||
|
// main
|
||||||
|
address := entity.Address("main.fspl")
|
||||||
|
ast, ok := treeOf(test, address, main, false)
|
||||||
|
if !ok { return }
|
||||||
|
err := tree.Analyze(address.UUID(), nicknames, ast)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("analyzer returned error:\n" + errors.Format(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testSemanticTree(test, correct, "", tree)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSemanticTree (test *testing.T, correct string, input string, tree analyzer.Tree) {
|
||||||
module, err := (&Target {
|
module, err := (&Target {
|
||||||
WordSize: 64,
|
WordSize: 64,
|
||||||
Arch: "x86_64",
|
Arch: "x86_64",
|
||||||
|
@ -47,8 +92,32 @@ func testString (test *testing.T, correct string, input string) {
|
||||||
if got != correct {
|
if got != correct {
|
||||||
test.Logf("results do not match")
|
test.Logf("results do not match")
|
||||||
testcommon.Compare(test, correct, got)
|
testcommon.Compare(test, correct, got)
|
||||||
test.Log("SOURCE FSPL CODE:")
|
if input != "" {
|
||||||
test.Log("\033[32m" + input + "\033[0m")
|
test.Log("SOURCE FSPL CODE:")
|
||||||
|
test.Log("\033[32m" + input + "\033[0m")
|
||||||
|
}
|
||||||
test.Fail()
|
test.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func treeOf (test *testing.T, address entity.Address, input string, skim bool) (fsplParser.Tree, bool) {
|
||||||
|
ast := fsplParser.Tree { }
|
||||||
|
lx, err := lexer.LexReader (
|
||||||
|
string(address),
|
||||||
|
strings.NewReader(input))
|
||||||
|
if err != nil {
|
||||||
|
test.Error("lexer returned error:\n" + errors.Format(err))
|
||||||
|
return ast, false
|
||||||
|
}
|
||||||
|
if skim {
|
||||||
|
err = ast.Skim(lx)
|
||||||
|
} else {
|
||||||
|
err = ast.Parse(lx)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
test.Error("parser returned error:\n" + errors.Format(err))
|
||||||
|
return ast, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return ast, true
|
||||||
|
}
|
||||||
|
|
|
@ -12,7 +12,12 @@ func (this *generator) generateTypedef (
|
||||||
) {
|
) {
|
||||||
irType, err := this.generateType(def.Type)
|
irType, err := this.generateType(def.Type)
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
return this.module.NewType(def.Name, irType), nil
|
irTypeDef := this.module.NewType(def.Name, irType)
|
||||||
|
this.types[entity.Key {
|
||||||
|
Unit: def.Unit,
|
||||||
|
Name: def.Name,
|
||||||
|
}] = irTypeDef
|
||||||
|
return irTypeDef, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *generator) generateType (ty entity.Type) (llvm.Type, error) {
|
func (this *generator) generateType (ty entity.Type) (llvm.Type, error) {
|
||||||
|
@ -41,9 +46,3 @@ func (this *generator) generateType (ty entity.Type) (llvm.Type, error) {
|
||||||
panic(fmt.Sprintln("generator doesn't know about type", ty))
|
panic(fmt.Sprintln("generator doesn't know about type", ty))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *generator) generateTypeIndex () (*llvm.TypeInt, error) {
|
|
||||||
sizeTypeAny, err := this.typedef("Index")
|
|
||||||
if err != nil { return nil, err }
|
|
||||||
return sizeTypeAny.(*llvm.TypeInt), nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,8 +6,19 @@ import "strings"
|
||||||
import "git.tebibyte.media/sashakoshka/fspl/llvm"
|
import "git.tebibyte.media/sashakoshka/fspl/llvm"
|
||||||
import "git.tebibyte.media/sashakoshka/fspl/entity"
|
import "git.tebibyte.media/sashakoshka/fspl/entity"
|
||||||
|
|
||||||
|
func (this *generator) generateTypeIndex () (*llvm.TypeInt, error) {
|
||||||
|
ty, err := this.typedef(entity.Key {
|
||||||
|
Name: "Index",
|
||||||
|
})
|
||||||
|
if err != nil { return nil, err }
|
||||||
|
return ty.(*llvm.TypeInt), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (this *generator) generateTypeNamed (ty *entity.TypeNamed) (llvm.Type, error) {
|
func (this *generator) generateTypeNamed (ty *entity.TypeNamed) (llvm.Type, error) {
|
||||||
underlying, err := this.typedef(ty.Name)
|
underlying, err := this.typedef(entity.Key {
|
||||||
|
Unit: ty.Type.Unit(),
|
||||||
|
Name: ty.Name,
|
||||||
|
})
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
return &llvm.TypeDefined { Source: underlying }, nil
|
return &llvm.TypeDefined { Source: underlying }, nil
|
||||||
}
|
}
|
||||||
|
@ -17,7 +28,7 @@ func (this *generator) generateTypePointer (ty *entity.TypePointer) (llvm.Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *generator) generateTypeSlice (ty *entity.TypeSlice) (llvm.Type, error) {
|
func (this *generator) generateTypeSlice (ty *entity.TypeSlice) (llvm.Type, error) {
|
||||||
indexType, err := this.typedef("Index")
|
indexType, err := this.generateTypeIndex()
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
return &llvm.TypeStruct {
|
return &llvm.TypeStruct {
|
||||||
Fields: []llvm.Type {
|
Fields: []llvm.Type {
|
||||||
|
|
Loading…
Reference in New Issue