Switched to pointer receivers for values

This commit is contained in:
Eduard Urbach 2025-03-01 18:38:00 +01:00
parent 8ff6faa310
commit 4428b09de2
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
17 changed files with 62 additions and 62 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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:

View File

@ -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)

View File

@ -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:

View File

@ -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,
} }

View File

@ -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,
} }

View File

@ -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]

View File

@ -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,
} }

View File

@ -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,
} }

View File

@ -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)
} }
} }

View File

@ -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)
} }
} }

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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--
}

View File

@ -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--
}