Switched to pointer receivers for values
This commit is contained in:
parent
8ff6faa310
commit
4428b09de2
@ -36,9 +36,9 @@ func (f *Function) CompileAssign(node *ast.Assign) error {
|
|||||||
operation := node.Expression.Token
|
operation := node.Expression.Token
|
||||||
|
|
||||||
switch leftValue := leftValue.(type) {
|
switch leftValue := leftValue.(type) {
|
||||||
case eval.Register:
|
case *eval.Register:
|
||||||
f.Execute(operation, leftValue.Register, right)
|
f.Execute(operation, leftValue.Register, right)
|
||||||
case eval.Memory:
|
case *eval.Memory:
|
||||||
if operation.Kind == token.Assign {
|
if operation.Kind == token.Assign {
|
||||||
rightValue, err := f.Evaluate(right)
|
rightValue, err := f.Evaluate(right)
|
||||||
|
|
||||||
|
@ -75,11 +75,11 @@ func (f *Function) CompileAssignDivision(expr *expression.Expression) error {
|
|||||||
divisor := division.Children[1]
|
divisor := division.Children[1]
|
||||||
|
|
||||||
switch dividend := dividend.(type) {
|
switch dividend := dividend.(type) {
|
||||||
case eval.Number:
|
case *eval.Number:
|
||||||
f.SaveRegister(x86.RAX)
|
f.SaveRegister(x86.RAX)
|
||||||
f.RegisterNumber(asm.MOVE, x86.RAX, dividend.Number)
|
f.RegisterNumber(asm.MOVE, x86.RAX, dividend.Number)
|
||||||
err = f.Execute(division.Token, x86.RAX, divisor)
|
err = f.Execute(division.Token, x86.RAX, divisor)
|
||||||
case eval.Register:
|
case *eval.Register:
|
||||||
if dividend.Register != quotientVariable.Value.Register && dividend.IsAlive() {
|
if dividend.Register != quotientVariable.Value.Register && dividend.IsAlive() {
|
||||||
tmp := f.NewRegister()
|
tmp := f.NewRegister()
|
||||||
f.RegisterRegister(asm.MOVE, tmp, dividend.Register)
|
f.RegisterRegister(asm.MOVE, tmp, dividend.Register)
|
||||||
|
@ -80,11 +80,11 @@ func (f *Function) CompileCondition(condition *expression.Expression, successLab
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case eval.Number:
|
case *eval.Number:
|
||||||
if value.Number == 0 {
|
if value.Number == 0 {
|
||||||
f.Jump(asm.JUMP, failLabel)
|
f.Jump(asm.JUMP, failLabel)
|
||||||
}
|
}
|
||||||
case eval.Register:
|
case *eval.Register:
|
||||||
f.RegisterNumber(asm.COMPARE, value.Register, 0)
|
f.RegisterNumber(asm.COMPARE, value.Register, 0)
|
||||||
f.Jump(asm.JE, failLabel)
|
f.Jump(asm.JE, failLabel)
|
||||||
default:
|
default:
|
||||||
|
@ -75,10 +75,10 @@ func (f *Function) CompileFor(loop *ast.For) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case eval.Number:
|
case *eval.Number:
|
||||||
f.AddLabel(label)
|
f.AddLabel(label)
|
||||||
f.RegisterNumber(asm.COMPARE, counter, value.Number)
|
f.RegisterNumber(asm.COMPARE, counter, value.Number)
|
||||||
case eval.Register:
|
case *eval.Register:
|
||||||
if value.IsAlive() {
|
if value.IsAlive() {
|
||||||
tmp := f.NewRegister()
|
tmp := f.NewRegister()
|
||||||
f.RegisterRegister(asm.MOVE, tmp, value.Register)
|
f.RegisterRegister(asm.MOVE, tmp, value.Register)
|
||||||
|
@ -35,9 +35,9 @@ func (f *Function) CompileLen(root *expression.Expression) error {
|
|||||||
f.SaveRegister(output)
|
f.SaveRegister(output)
|
||||||
|
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case eval.Register:
|
case *eval.Register:
|
||||||
memory.Base = value.Register
|
memory.Base = value.Register
|
||||||
case eval.Label:
|
case *eval.Label:
|
||||||
f.RegisterLabel(asm.MOVE, output, value.Label)
|
f.RegisterLabel(asm.MOVE, output, value.Label)
|
||||||
memory.Base = output
|
memory.Base = output
|
||||||
default:
|
default:
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
// Evaluate evaluates an expression and returns a value.
|
// Evaluate evaluates an expression and returns a value.
|
||||||
func (f *Function) Evaluate(expr *expression.Expression) (eval.Value, error) {
|
func (f *Function) Evaluate(expr *expression.Expression) (eval.Value, error) {
|
||||||
if expr.IsFolded {
|
if expr.IsFolded {
|
||||||
value := eval.Number{
|
value := &eval.Number{
|
||||||
Typ: types.AnyInt,
|
Typ: types.AnyInt,
|
||||||
Number: expr.Value,
|
Number: expr.Value,
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ func (f *Function) Evaluate(expr *expression.Expression) (eval.Value, error) {
|
|||||||
tmp := f.NewRegister()
|
tmp := f.NewRegister()
|
||||||
typ, err := f.ExpressionToRegister(expr, tmp)
|
typ, err := f.ExpressionToRegister(expr, tmp)
|
||||||
|
|
||||||
value := eval.Register{
|
value := &eval.Register{
|
||||||
Typ: typ,
|
Typ: typ,
|
||||||
Register: tmp,
|
Register: tmp,
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// EvaluateArray evaluates an array access.
|
// EvaluateArray evaluates an array access.
|
||||||
func (f *Function) EvaluateArray(expr *expression.Expression) (eval.Memory, error) {
|
func (f *Function) EvaluateArray(expr *expression.Expression) (*eval.Memory, error) {
|
||||||
name := expr.Children[0].Token.Text(f.File.Bytes)
|
name := expr.Children[0].Token.Text(f.File.Bytes)
|
||||||
base := f.VariableByName(name)
|
base := f.VariableByName(name)
|
||||||
|
|
||||||
if base == nil {
|
if base == nil {
|
||||||
return eval.Memory{}, errors.New(&errors.UnknownIdentifier{Name: name}, f.File, expr.Children[0].Token.Position)
|
return nil, errors.New(&errors.UnknownIdentifier{Name: name}, f.File, expr.Children[0].Token.Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer f.UseVariable(base)
|
defer f.UseVariable(base)
|
||||||
@ -33,17 +33,17 @@ func (f *Function) EvaluateArray(expr *expression.Expression) (eval.Memory, erro
|
|||||||
index, err := f.Evaluate(indexExpr)
|
index, err := f.Evaluate(indexExpr)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return eval.Memory{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !types.Is(index.Type(), types.AnyInt) {
|
if !types.Is(index.Type(), types.AnyInt) {
|
||||||
return eval.Memory{}, errors.New(&errors.TypeMismatch{Encountered: index.Type().Name(), Expected: types.AnyInt.Name()}, f.File, indexExpr.Token.Position)
|
return nil, errors.New(&errors.TypeMismatch{Encountered: index.Type().Name(), Expected: types.AnyInt.Name()}, f.File, indexExpr.Token.Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch index := index.(type) {
|
switch index := index.(type) {
|
||||||
case eval.Number:
|
case *eval.Number:
|
||||||
memory.Offset = int8(index.Number)
|
memory.Offset = int8(index.Number)
|
||||||
case eval.Register:
|
case *eval.Register:
|
||||||
memory.OffsetRegister = index.Register
|
memory.OffsetRegister = index.Register
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("%s: not implemented: %v", f.UniqueName, index))
|
panic(fmt.Errorf("%s: not implemented: %v", f.UniqueName, index))
|
||||||
@ -52,7 +52,7 @@ func (f *Function) EvaluateArray(expr *expression.Expression) (eval.Memory, erro
|
|||||||
array, isArray := base.Value.Typ.(*types.Array)
|
array, isArray := base.Value.Typ.(*types.Array)
|
||||||
|
|
||||||
if isArray {
|
if isArray {
|
||||||
value := eval.Memory{
|
value := &eval.Memory{
|
||||||
Typ: array.Of,
|
Typ: array.Of,
|
||||||
Memory: memory,
|
Memory: memory,
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ func (f *Function) EvaluateArray(expr *expression.Expression) (eval.Memory, erro
|
|||||||
pointer, isPointer := base.Value.Typ.(*types.Pointer)
|
pointer, isPointer := base.Value.Typ.(*types.Pointer)
|
||||||
|
|
||||||
if isPointer {
|
if isPointer {
|
||||||
value := eval.Memory{
|
value := &eval.Memory{
|
||||||
Typ: pointer.To,
|
Typ: pointer.To,
|
||||||
Memory: memory,
|
Memory: memory,
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// EvaluateCall evaluates a function call.
|
// EvaluateCall evaluates a function call.
|
||||||
func (f *Function) EvaluateCall(expr *expression.Expression) (eval.Register, error) {
|
func (f *Function) EvaluateCall(expr *expression.Expression) (*eval.Register, error) {
|
||||||
typ, err := f.CompileCall(expr)
|
typ, err := f.CompileCall(expr)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return eval.Register{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
value := eval.Register{Register: f.CPU.Output[0]}
|
value := &eval.Register{Register: f.CPU.Output[0]}
|
||||||
|
|
||||||
if len(typ) > 0 {
|
if len(typ) > 0 {
|
||||||
value.Typ = typ[0]
|
value.Typ = typ[0]
|
||||||
|
@ -29,7 +29,7 @@ func (f *Function) EvaluateDot(expr *expression.Expression) (eval.Value, error)
|
|||||||
return nil, errors.New(&errors.UnknownStructField{StructName: structure.Name(), FieldName: rightText}, f.File, right.Token.Position)
|
return nil, errors.New(&errors.UnknownStructField{StructName: structure.Name(), FieldName: rightText}, f.File, right.Token.Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
value := eval.Memory{
|
value := &eval.Memory{
|
||||||
Typ: field.Type,
|
Typ: field.Type,
|
||||||
Memory: asm.Memory{
|
Memory: asm.Memory{
|
||||||
Base: variable.Value.Register,
|
Base: variable.Value.Register,
|
||||||
@ -51,7 +51,7 @@ func (f *Function) EvaluateDot(expr *expression.Expression) (eval.Value, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
value := eval.Number{
|
value := &eval.Number{
|
||||||
Typ: types.AnyInt,
|
Typ: types.AnyInt,
|
||||||
Number: number,
|
Number: number,
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ func (f *Function) EvaluateDot(expr *expression.Expression) (eval.Value, error)
|
|||||||
if exists {
|
if exists {
|
||||||
f.File.Imports[leftText].Used = true
|
f.File.Imports[leftText].Used = true
|
||||||
|
|
||||||
value := eval.Label{
|
value := &eval.Label{
|
||||||
Typ: types.AnyPointer,
|
Typ: types.AnyPointer,
|
||||||
Label: function.UniqueName,
|
Label: function.UniqueName,
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ func (f *Function) EvaluateToken(t token.Token) (eval.Value, error) {
|
|||||||
name := t.Text(f.File.Bytes)
|
name := t.Text(f.File.Bytes)
|
||||||
|
|
||||||
if name == "true" {
|
if name == "true" {
|
||||||
value := eval.Number{
|
value := &eval.Number{
|
||||||
Typ: types.Bool,
|
Typ: types.Bool,
|
||||||
Number: 1,
|
Number: 1,
|
||||||
}
|
}
|
||||||
@ -25,7 +25,7 @@ func (f *Function) EvaluateToken(t token.Token) (eval.Value, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if name == "false" {
|
if name == "false" {
|
||||||
value := eval.Number{
|
value := &eval.Number{
|
||||||
Typ: types.Bool,
|
Typ: types.Bool,
|
||||||
Number: 0,
|
Number: 0,
|
||||||
}
|
}
|
||||||
@ -37,11 +37,11 @@ func (f *Function) EvaluateToken(t token.Token) (eval.Value, error) {
|
|||||||
|
|
||||||
if variable != nil {
|
if variable != nil {
|
||||||
f.UseVariable(variable)
|
f.UseVariable(variable)
|
||||||
return variable.Value, nil
|
return &variable.Value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if function != nil {
|
if function != nil {
|
||||||
value := eval.Label{
|
value := &eval.Label{
|
||||||
Typ: types.AnyPointer,
|
Typ: types.AnyPointer,
|
||||||
Label: function.UniqueName,
|
Label: function.UniqueName,
|
||||||
}
|
}
|
||||||
@ -58,7 +58,7 @@ func (f *Function) EvaluateToken(t token.Token) (eval.Value, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
value := eval.Number{
|
value := &eval.Number{
|
||||||
Typ: types.AnyInt,
|
Typ: types.AnyInt,
|
||||||
Number: number,
|
Number: number,
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ func (f *Function) EvaluateToken(t token.Token) (eval.Value, error) {
|
|||||||
copy(slice[8:], data)
|
copy(slice[8:], data)
|
||||||
label := f.AddBytes(slice)
|
label := f.AddBytes(slice)
|
||||||
|
|
||||||
value := eval.Label{
|
value := &eval.Label{
|
||||||
Typ: types.String,
|
Typ: types.String,
|
||||||
Label: label,
|
Label: label,
|
||||||
}
|
}
|
||||||
|
@ -8,16 +8,16 @@ import (
|
|||||||
// ValueToMemory moves a value into a memory region.
|
// ValueToMemory moves a value into a memory region.
|
||||||
func (f *Function) ValueToMemory(value eval.Value, memory asm.Memory) {
|
func (f *Function) ValueToMemory(value eval.Value, memory asm.Memory) {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case eval.Number:
|
case *eval.Number:
|
||||||
f.MemoryNumber(asm.STORE, memory, value.Number)
|
f.MemoryNumber(asm.STORE, memory, value.Number)
|
||||||
case eval.Register:
|
case *eval.Register:
|
||||||
f.MemoryRegister(asm.STORE, memory, value.Register)
|
f.MemoryRegister(asm.STORE, memory, value.Register)
|
||||||
case eval.Memory:
|
case *eval.Memory:
|
||||||
tmp := f.NewRegister()
|
tmp := f.NewRegister()
|
||||||
f.MemoryRegister(asm.LOAD, value.Memory, tmp)
|
f.MemoryRegister(asm.LOAD, value.Memory, tmp)
|
||||||
f.MemoryRegister(asm.STORE, memory, tmp)
|
f.MemoryRegister(asm.STORE, memory, tmp)
|
||||||
f.FreeRegister(tmp)
|
f.FreeRegister(tmp)
|
||||||
case eval.Label:
|
case *eval.Label:
|
||||||
f.MemoryLabel(asm.STORE, memory, value.Label)
|
f.MemoryLabel(asm.STORE, memory, value.Label)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,13 @@ import (
|
|||||||
// ValueToRegister moves a value into a register.
|
// ValueToRegister moves a value into a register.
|
||||||
func (f *Function) ValueToRegister(value eval.Value, register cpu.Register) {
|
func (f *Function) ValueToRegister(value eval.Value, register cpu.Register) {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case eval.Number:
|
case *eval.Number:
|
||||||
f.RegisterNumber(asm.MOVE, register, value.Number)
|
f.RegisterNumber(asm.MOVE, register, value.Number)
|
||||||
case eval.Register:
|
case *eval.Register:
|
||||||
f.RegisterRegister(asm.MOVE, register, value.Register)
|
f.RegisterRegister(asm.MOVE, register, value.Register)
|
||||||
case eval.Memory:
|
case *eval.Memory:
|
||||||
f.MemoryRegister(asm.LOAD, value.Memory, register)
|
f.MemoryRegister(asm.LOAD, value.Memory, register)
|
||||||
case eval.Label:
|
case *eval.Label:
|
||||||
f.RegisterLabel(asm.MOVE, register, value.Label)
|
f.RegisterLabel(asm.MOVE, register, value.Label)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,10 @@ type Label struct {
|
|||||||
Label string
|
Label string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Label) String() string {
|
func (v *Label) String() string {
|
||||||
return "Label"
|
return "Label"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Label) Type() types.Type {
|
func (v *Label) Type() types.Type {
|
||||||
return v.Typ
|
return v.Typ
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,10 @@ type Memory struct {
|
|||||||
Memory asm.Memory
|
Memory asm.Memory
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Memory) String() string {
|
func (v *Memory) String() string {
|
||||||
return "Memory"
|
return "Memory"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Memory) Type() types.Type {
|
func (v *Memory) Type() types.Type {
|
||||||
return v.Typ
|
return v.Typ
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,10 @@ type Number struct {
|
|||||||
Number int
|
Number int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Number) String() string {
|
func (v *Number) String() string {
|
||||||
return "Number"
|
return "Number"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Number) Type() types.Type {
|
func (v *Number) Type() types.Type {
|
||||||
return v.Typ
|
return v.Typ
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,24 @@ type Register struct {
|
|||||||
Register cpu.Register
|
Register cpu.Register
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Register) String() string {
|
func (v *Register) String() string {
|
||||||
return "Register"
|
return "Register"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Register) Type() types.Type {
|
func (v *Register) Type() types.Type {
|
||||||
return v.Typ
|
return v.Typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsAlive returns true if the register value is still alive.
|
||||||
|
func (v *Register) IsAlive() bool {
|
||||||
|
return v.Alive > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use reduces the lifetime counter by one.
|
||||||
|
func (v *Register) Use() {
|
||||||
|
if v.Alive == 0 {
|
||||||
|
panic("incorrect number of value use calls")
|
||||||
|
}
|
||||||
|
|
||||||
|
v.Alive--
|
||||||
|
}
|
||||||
|
@ -9,17 +9,3 @@ type Value interface {
|
|||||||
String() string
|
String() string
|
||||||
Type() types.Type
|
Type() types.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsAlive returns true if the register value is still alive.
|
|
||||||
func (v *Register) IsAlive() bool {
|
|
||||||
return v.Alive > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use reduces the lifetime counter by one.
|
|
||||||
func (v *Register) Use() {
|
|
||||||
if v.Alive == 0 {
|
|
||||||
panic("incorrect number of value use calls")
|
|
||||||
}
|
|
||||||
|
|
||||||
v.Alive--
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user