Added Value type
This commit is contained in:
parent
ae6530aadb
commit
9f78733d5d
@ -30,31 +30,31 @@ func (f *Function) CompileAssignArray(node *ast.Assign) error {
|
||||
Length: byte(1),
|
||||
}
|
||||
|
||||
index := left.Children[1]
|
||||
indexExpr := left.Children[1]
|
||||
|
||||
if index.Token.IsNumeric() {
|
||||
offset, err := f.ToNumber(index.Token)
|
||||
if indexExpr.Token.IsNumeric() {
|
||||
index, err := f.ToNumber(indexExpr.Token)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
memory.Offset = int8(offset)
|
||||
memory.Offset = int8(index)
|
||||
} else {
|
||||
typ, indexRegister, isTemporary, err := f.Evaluate(index)
|
||||
index, isTemporary, err := f.Evaluate(indexExpr)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !types.Is(typ, types.AnyInt) {
|
||||
return errors.New(&errors.TypeMismatch{Encountered: typ.Name(), Expected: types.AnyInt.Name()}, f.File, index.Token.Position)
|
||||
if !types.Is(index.Type, types.AnyInt) {
|
||||
return errors.New(&errors.TypeMismatch{Encountered: index.Type.Name(), Expected: types.AnyInt.Name()}, f.File, indexExpr.Token.Position)
|
||||
}
|
||||
|
||||
memory.OffsetRegister = indexRegister
|
||||
memory.OffsetRegister = index.Register
|
||||
|
||||
if isTemporary {
|
||||
defer f.FreeRegister(indexRegister)
|
||||
defer f.FreeRegister(index.Register)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,20 +58,24 @@ func (f *Function) CompileAssignDivision(expr *expression.Expression) error {
|
||||
defer f.UseVariable(remainderVariable)
|
||||
}
|
||||
|
||||
dividend := right.Children[0]
|
||||
_, dividendRegister, isTemporary, err := f.Evaluate(dividend)
|
||||
dividendExpr := right.Children[0]
|
||||
dividend, isTemporary, err := f.Evaluate(dividendExpr)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !types.Is(dividend.Type, types.AnyInt) {
|
||||
return errors.New(&errors.TypeMismatch{Encountered: dividend.Type.Name(), Expected: types.AnyInt.Name()}, f.File, dividendExpr.Token.Position)
|
||||
}
|
||||
|
||||
divisor := right.Children[1]
|
||||
err = f.Execute(right.Token, dividendRegister, divisor)
|
||||
err = f.Execute(right.Token, dividend.Register, divisor)
|
||||
f.RegisterRegister(asm.MOVE, quotientVariable.Register, x86.RAX)
|
||||
f.RegisterRegister(asm.MOVE, remainderVariable.Register, x86.RDX)
|
||||
|
||||
if isTemporary {
|
||||
f.FreeRegister(dividendRegister)
|
||||
f.FreeRegister(dividend.Register)
|
||||
}
|
||||
|
||||
return err
|
||||
|
@ -4,8 +4,10 @@ import (
|
||||
"git.urbach.dev/cli/q/src/asm"
|
||||
"git.urbach.dev/cli/q/src/ast"
|
||||
"git.urbach.dev/cli/q/src/cpu"
|
||||
"git.urbach.dev/cli/q/src/errors"
|
||||
"git.urbach.dev/cli/q/src/expression"
|
||||
"git.urbach.dev/cli/q/src/token"
|
||||
"git.urbach.dev/cli/q/src/types"
|
||||
)
|
||||
|
||||
// CompileFor compiles a for loop.
|
||||
@ -66,18 +68,22 @@ func (f *Function) CompileFor(loop *ast.For) error {
|
||||
f.AddLabel(label)
|
||||
f.RegisterNumber(asm.COMPARE, counter, number)
|
||||
} else {
|
||||
_, register, isTemporary, err := f.Evaluate(to)
|
||||
value, isTemporary, err := f.Evaluate(to)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !types.Is(value.Type, types.AnyInt) {
|
||||
return errors.New(&errors.TypeMismatch{Encountered: value.Type.Name(), Expected: types.AnyInt.Name()}, f.File, to.Token.Position)
|
||||
}
|
||||
|
||||
if isTemporary {
|
||||
defer f.FreeRegister(register)
|
||||
defer f.FreeRegister(value.Register)
|
||||
}
|
||||
|
||||
f.AddLabel(label)
|
||||
f.RegisterRegister(asm.COMPARE, counter, register)
|
||||
f.RegisterRegister(asm.COMPARE, counter, value.Register)
|
||||
}
|
||||
|
||||
f.Jump(asm.JGE, labelEnd)
|
||||
|
@ -13,21 +13,21 @@ var _len = Function{OutputTypes: []types.Type{types.AnyInt}}
|
||||
|
||||
// CompileLen returns the length of a slice.
|
||||
func (f *Function) CompileLen(root *expression.Expression) error {
|
||||
typ, register, isTemporary, err := f.Evaluate(root.Children[1])
|
||||
value, isTemporary, err := f.Evaluate(root.Children[1])
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !types.Is(typ, types.AnyArray) {
|
||||
return errors.New(&errors.TypeMismatch{Encountered: typ.Name(), Expected: types.AnyArray.Name(), ParameterName: "array"}, f.File, root.Children[1].Token.Position)
|
||||
if !types.Is(value.Type, types.AnyArray) {
|
||||
return errors.New(&errors.TypeMismatch{Encountered: value.Type.Name(), Expected: types.AnyArray.Name(), ParameterName: "array"}, f.File, root.Children[1].Token.Position)
|
||||
}
|
||||
|
||||
f.SaveRegister(f.CPU.Output[0])
|
||||
f.MemoryRegister(asm.LOAD, asm.Memory{Base: register, Offset: -8, OffsetRegister: math.MaxUint8, Length: 8}, f.CPU.Output[0])
|
||||
f.MemoryRegister(asm.LOAD, asm.Memory{Base: value.Register, Offset: -8, OffsetRegister: math.MaxUint8, Length: 8}, f.CPU.Output[0])
|
||||
|
||||
if isTemporary {
|
||||
f.FreeRegister(register)
|
||||
f.FreeRegister(value.Register)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -2,26 +2,24 @@ package core
|
||||
|
||||
import (
|
||||
"git.urbach.dev/cli/q/src/ast"
|
||||
"git.urbach.dev/cli/q/src/cpu"
|
||||
"git.urbach.dev/cli/q/src/errors"
|
||||
"git.urbach.dev/cli/q/src/expression"
|
||||
"git.urbach.dev/cli/q/src/token"
|
||||
"git.urbach.dev/cli/q/src/types"
|
||||
)
|
||||
|
||||
// Evaluate evaluates an expression and returns a register that contains the value of the expression.
|
||||
func (f *Function) Evaluate(expr *expression.Expression) (types.Type, cpu.Register, bool, error) {
|
||||
func (f *Function) Evaluate(expr *expression.Expression) (Value, bool, error) {
|
||||
if expr.Token.Kind == token.Identifier {
|
||||
name := expr.Token.Text(f.File.Bytes)
|
||||
variable := f.VariableByName(name)
|
||||
|
||||
if variable == nil {
|
||||
return nil, 0, false, errors.New(&errors.UnknownIdentifier{Name: name}, f.File, expr.Token.Position)
|
||||
return Value{}, false, errors.New(&errors.UnknownIdentifier{Name: name}, f.File, expr.Token.Position)
|
||||
}
|
||||
|
||||
if variable.Alive == 1 {
|
||||
f.UseVariable(variable)
|
||||
return variable.Type, variable.Register, false, nil
|
||||
return Value{variable.Type, variable.Register}, false, nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,13 +27,13 @@ func (f *Function) Evaluate(expr *expression.Expression) (types.Type, cpu.Regist
|
||||
types, err := f.CompileCall(expr)
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, false, err
|
||||
return Value{}, false, err
|
||||
}
|
||||
|
||||
return types[0], f.CPU.Output[0], false, nil
|
||||
return Value{types[0], f.CPU.Output[0]}, false, nil
|
||||
}
|
||||
|
||||
tmp := f.NewRegister()
|
||||
typ, err := f.ExpressionToRegister(expr, tmp)
|
||||
return typ, tmp, true, err
|
||||
return Value{typ, tmp}, true, err
|
||||
}
|
||||
|
@ -52,17 +52,17 @@ func (f *Function) ExpressionToMemory(node *expression.Expression, memory asm.Me
|
||||
}
|
||||
}
|
||||
|
||||
typ, register, isTemporary, err := f.Evaluate(node)
|
||||
value, isTemporary, err := f.Evaluate(node)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f.MemoryRegister(asm.STORE, memory, register)
|
||||
f.MemoryRegister(asm.STORE, memory, value.Register)
|
||||
|
||||
if isTemporary {
|
||||
f.FreeRegister(register)
|
||||
f.FreeRegister(value.Register)
|
||||
}
|
||||
|
||||
return typ, err
|
||||
return value.Type, err
|
||||
}
|
||||
|
12
src/core/Value.go
Normal file
12
src/core/Value.go
Normal file
@ -0,0 +1,12 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"git.urbach.dev/cli/q/src/cpu"
|
||||
"git.urbach.dev/cli/q/src/types"
|
||||
)
|
||||
|
||||
// Value combines a register with its data type.
|
||||
type Value struct {
|
||||
Type types.Type
|
||||
Register cpu.Register
|
||||
}
|
@ -27,8 +27,19 @@ func Is(a Type, b Type) bool {
|
||||
|
||||
if a == AnyInt {
|
||||
switch b {
|
||||
case Int64, Int32, Int16, Int8, UInt64, UInt32, UInt16, UInt8:
|
||||
case Int64, Int32, Int16, Int8, UInt64, UInt32, UInt16, UInt8, AnyInt:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if b == AnyInt {
|
||||
switch a {
|
||||
case Int64, Int32, Int16, Int8, UInt64, UInt32, UInt16, UInt8, AnyInt:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user