diff --git a/generator/constant.go b/generator/constant.go index 2b7fac3..e9edaa7 100644 --- a/generator/constant.go +++ b/generator/constant.go @@ -1,50 +1,44 @@ package generator -import "fmt" -import "errors" import "git.tebibyte.media/fspl/fspl/llvm" import "git.tebibyte.media/fspl/fspl/entity" -import "git.tebibyte.media/fspl/fspl/analyzer" -func (this *generator) generateConstantInt (literal *entity.LiteralInt) (llvm.Const, error) { - irType, err := this.generateType(analyzer.ReduceToBase(literal.Type())) - if err != nil { return nil, err } - - base := analyzer.ReduceToBase(literal.Type()) - switch base.(type) { - case *entity.TypeInt, *entity.TypeWord: - return llvm.NewConstInt(irType.(*llvm.TypeInt), int64(literal.Value)), nil - case *entity.TypeFloat: - return llvm.NewConstFloat(irType.(*llvm.TypeFloat), float64(literal.Value)), nil - default: - return nil, errors.New(fmt.Sprintln("int can't be used as", base)) +func (this *generator) generateConstantDeclaration ( + ty *entity.Typedef, + constantName string, +) ( + *llvm.Global, + error, +) { + key := entity.Key { + Unit: ty.Unit(), + Type: ty.Name, + Constant: constantName, } -} + constant := ty.ConstantMap[constantName] -func (this *generator) generateConstantFloat (literal *entity.LiteralFloat) (llvm.Const, error) { - irType, err := this.generateType(analyzer.ReduceToBase(literal.Type())) + irType, err := this.typedef(key.OnlyType()) if err != nil { return nil, err } - return llvm.NewConstFloat(irType.(*llvm.TypeFloat), literal.Value), nil -} -func (this *generator) generateConstantString (literal *entity.LiteralString) (llvm.Const, error) { - panic("BUG: not supported yet") -} + // TODO: have two maps, constantsVal and constantsLoc. if the constant + // is multivalue, generate a constant global and put it in constantsLoc. + // if not, put the value in constantsVal. have generator.constant try + // both. have single generateConstant method that converts if necessary + // by either loading or allocating a copy on the stack. + // + // have a Multivalue method of types and disallow referencing of + // non-multivalue constants. + + irGlobal := this.module.NewGlobal(constantName, irType) + irGlobal.Constant = true -func (this *generator) generateConstantArray (literal *entity.LiteralArray) (llvm.Const, error) { - panic("BUG: not supported yet") -} - -func (this *generator) generateConstantStruct (literal *entity.LiteralStruct) (llvm.Const, error) { - panic("BUG: not supported yet") -} - -func (this *generator) generateConstantBoolean (literal *entity.LiteralBoolean) (llvm.Const, error) { - return llvm.NewConstBool(bool(literal.Value)), nil -} - -func (this *generator) generateConstantNil (literal *entity.LiteralNil) (llvm.Const, error) { - ty, err := this.generateType(literal.Type()) - if err != nil { return nil, err } - return llvm.NewConstZeroInitializer(ty), nil + if ty.Unit() == this.tree.Unit() { + // in root unit, so generate data + initial, err := this.generateEvaluated(constant.Value) + if err != nil { return nil, err } + irGlobal.Initial = initial + } + + this.constants[key] = irGlobal + return irGlobal, nil } diff --git a/generator/constantdef.go b/generator/constantdef.go deleted file mode 100644 index 2d340ed..0000000 --- a/generator/constantdef.go +++ /dev/null @@ -1,35 +0,0 @@ -package generator - -import "git.tebibyte.media/fspl/fspl/llvm" -import "git.tebibyte.media/fspl/fspl/entity" - -func (this *generator) generateConstantDeclaration ( - ty *entity.Typedef, - constantName string, -) ( - *llvm.Global, - error, -) { - key := entity.Key { - Unit: ty.Unit(), - Type: ty.Name, - Constant: constantName, - } - constant := ty.ConstantMap[constantName] - - irType, err := this.typedef(key.OnlyType()) - if err != nil { return nil, err } - - irGlobal := this.module.NewGlobal(constantName, irType) - irGlobal.Constant = true - - if ty.Unit() == this.tree.Unit() { - // in root unit, so generate data - initial, err := this.generateConstant(constant.Value) - if err != nil { return nil, err } - irGlobal.Initial = initial - } - - this.constants[key] = irGlobal - return irGlobal, nil -} diff --git a/generator/constant-multiplex.go b/generator/evaluated-multiplex.go similarity index 53% rename from generator/constant-multiplex.go rename to generator/evaluated-multiplex.go index 84edb83..65bb055 100644 --- a/generator/constant-multiplex.go +++ b/generator/evaluated-multiplex.go @@ -4,22 +4,22 @@ import "fmt" import "git.tebibyte.media/fspl/fspl/llvm" import "git.tebibyte.media/fspl/fspl/entity" -func (this *generator) generateConstant (constant entity.Expression) (llvm.Const, error) { +func (this *generator) generateEvaluated (constant entity.Expression) (llvm.Const, error) { switch constant := constant.(type) { case *entity.LiteralInt: - return this.generateConstantInt(constant) + return this.generateEvaluatedInt(constant) case *entity.LiteralFloat: - return this.generateConstantFloat(constant) + return this.generateEvaluatedFloat(constant) case *entity.LiteralString: - return this.generateConstantString(constant) + return this.generateEvaluatedString(constant) case *entity.LiteralArray: - return this.generateConstantArray(constant) + return this.generateEvaluatedArray(constant) case *entity.LiteralStruct: - return this.generateConstantStruct(constant) + return this.generateEvaluatedStruct(constant) case *entity.LiteralBoolean: - return this.generateConstantBoolean(constant) + return this.generateEvaluatedBoolean(constant) case *entity.LiteralNil: - return this.generateConstantNil(constant) + return this.generateEvaluatedNil(constant) default: panic(fmt.Sprintf ( "BUG: generator doesnt know about constant %v, ty: %T", diff --git a/generator/evaluated.go b/generator/evaluated.go new file mode 100644 index 0000000..54f374c --- /dev/null +++ b/generator/evaluated.go @@ -0,0 +1,50 @@ +package generator + +import "fmt" +import "errors" +import "git.tebibyte.media/fspl/fspl/llvm" +import "git.tebibyte.media/fspl/fspl/entity" +import "git.tebibyte.media/fspl/fspl/analyzer" + +func (this *generator) generateEvaluatedInt (literal *entity.LiteralInt) (llvm.Const, error) { + irType, err := this.generateType(analyzer.ReduceToBase(literal.Type())) + if err != nil { return nil, err } + + base := analyzer.ReduceToBase(literal.Type()) + switch base.(type) { + case *entity.TypeInt, *entity.TypeWord: + return llvm.NewConstInt(irType.(*llvm.TypeInt), int64(literal.Value)), nil + case *entity.TypeFloat: + return llvm.NewConstFloat(irType.(*llvm.TypeFloat), float64(literal.Value)), nil + default: + return nil, errors.New(fmt.Sprintln("int can't be used as", base)) + } +} + +func (this *generator) generateEvaluatedFloat (literal *entity.LiteralFloat) (llvm.Const, error) { + irType, err := this.generateType(analyzer.ReduceToBase(literal.Type())) + if err != nil { return nil, err } + return llvm.NewConstFloat(irType.(*llvm.TypeFloat), literal.Value), nil +} + +func (this *generator) generateEvaluatedString (literal *entity.LiteralString) (llvm.Const, error) { + panic("BUG: not supported yet") +} + +func (this *generator) generateEvaluatedArray (literal *entity.LiteralArray) (llvm.Const, error) { + panic("BUG: not supported yet") +} + +func (this *generator) generateEvaluatedStruct (literal *entity.LiteralStruct) (llvm.Const, error) { + panic("BUG: not supported yet") +} + +func (this *generator) generateEvaluatedBoolean (literal *entity.LiteralBoolean) (llvm.Const, error) { + return llvm.NewConstBool(bool(literal.Value)), nil +} + +func (this *generator) generateEvaluatedNil (literal *entity.LiteralNil) (llvm.Const, error) { + ty, err := this.generateType(literal.Type()) + if err != nil { return nil, err } + return llvm.NewConstZeroInitializer(ty), nil +} diff --git a/generator/literal.go b/generator/literal.go index 117ea15..b15ba45 100644 --- a/generator/literal.go +++ b/generator/literal.go @@ -7,11 +7,11 @@ import "git.tebibyte.media/fspl/fspl/entity" import "git.tebibyte.media/fspl/fspl/analyzer" func (this *generator) generateLiteralInt (literal *entity.LiteralInt) (llvm.Value, error) { - return this.generateConstant(literal) + return this.generateEvaluated(literal) } func (this *generator) generateLiteralFloat (literal *entity.LiteralFloat) (llvm.Value, error) { - return this.generateConstant(literal) + return this.generateEvaluated(literal) } // generateLiteralArrayLoc generates an array literal. irDestLoc specifies the @@ -256,9 +256,9 @@ func (this *generator) generateLiteralStructLoc (literal *entity.LiteralStruct, } func (this *generator) generateLiteralBoolean (literal *entity.LiteralBoolean) (llvm.Value, error) { - return this.generateConstant(literal) + return this.generateEvaluated(literal) } func (this *generator) generateLiteralNil (literal *entity.LiteralNil) (llvm.Value, error) { - return this.generateConstant(literal) + return this.generateEvaluated(literal) }