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
|
||||
|
||||
switch leftValue := leftValue.(type) {
|
||||
case eval.Register:
|
||||
case *eval.Register:
|
||||
f.Execute(operation, leftValue.Register, right)
|
||||
case eval.Memory:
|
||||
case *eval.Memory:
|
||||
if operation.Kind == token.Assign {
|
||||
rightValue, err := f.Evaluate(right)
|
||||
|
||||
|
@ -75,11 +75,11 @@ func (f *Function) CompileAssignDivision(expr *expression.Expression) error {
|
||||
divisor := division.Children[1]
|
||||
|
||||
switch dividend := dividend.(type) {
|
||||
case eval.Number:
|
||||
case *eval.Number:
|
||||
f.SaveRegister(x86.RAX)
|
||||
f.RegisterNumber(asm.MOVE, x86.RAX, dividend.Number)
|
||||
err = f.Execute(division.Token, x86.RAX, divisor)
|
||||
case eval.Register:
|
||||
case *eval.Register:
|
||||
if dividend.Register != quotientVariable.Value.Register && dividend.IsAlive() {
|
||||
tmp := f.NewRegister()
|
||||
f.RegisterRegister(asm.MOVE, tmp, dividend.Register)
|
||||
|
@ -80,11 +80,11 @@ func (f *Function) CompileCondition(condition *expression.Expression, successLab
|
||||
}
|
||||
|
||||
switch value := value.(type) {
|
||||
case eval.Number:
|
||||
case *eval.Number:
|
||||
if value.Number == 0 {
|
||||
f.Jump(asm.JUMP, failLabel)
|
||||
}
|
||||
case eval.Register:
|
||||
case *eval.Register:
|
||||
f.RegisterNumber(asm.COMPARE, value.Register, 0)
|
||||
f.Jump(asm.JE, failLabel)
|
||||
default:
|
||||
|
@ -75,10 +75,10 @@ func (f *Function) CompileFor(loop *ast.For) error {
|
||||
}
|
||||
|
||||
switch value := value.(type) {
|
||||
case eval.Number:
|
||||
case *eval.Number:
|
||||
f.AddLabel(label)
|
||||
f.RegisterNumber(asm.COMPARE, counter, value.Number)
|
||||
case eval.Register:
|
||||
case *eval.Register:
|
||||
if value.IsAlive() {
|
||||
tmp := f.NewRegister()
|
||||
f.RegisterRegister(asm.MOVE, tmp, value.Register)
|
||||
|
@ -35,9 +35,9 @@ func (f *Function) CompileLen(root *expression.Expression) error {
|
||||
f.SaveRegister(output)
|
||||
|
||||
switch value := value.(type) {
|
||||
case eval.Register:
|
||||
case *eval.Register:
|
||||
memory.Base = value.Register
|
||||
case eval.Label:
|
||||
case *eval.Label:
|
||||
f.RegisterLabel(asm.MOVE, output, value.Label)
|
||||
memory.Base = output
|
||||
default:
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
// Evaluate evaluates an expression and returns a value.
|
||||
func (f *Function) Evaluate(expr *expression.Expression) (eval.Value, error) {
|
||||
if expr.IsFolded {
|
||||
value := eval.Number{
|
||||
value := &eval.Number{
|
||||
Typ: types.AnyInt,
|
||||
Number: expr.Value,
|
||||
}
|
||||
@ -36,7 +36,7 @@ func (f *Function) Evaluate(expr *expression.Expression) (eval.Value, error) {
|
||||
tmp := f.NewRegister()
|
||||
typ, err := f.ExpressionToRegister(expr, tmp)
|
||||
|
||||
value := eval.Register{
|
||||
value := &eval.Register{
|
||||
Typ: typ,
|
||||
Register: tmp,
|
||||
}
|
||||
|
@ -12,12 +12,12 @@ import (
|
||||
)
|
||||
|
||||
// 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)
|
||||
base := f.VariableByName(name)
|
||||
|
||||
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)
|
||||
@ -33,17 +33,17 @@ func (f *Function) EvaluateArray(expr *expression.Expression) (eval.Memory, erro
|
||||
index, err := f.Evaluate(indexExpr)
|
||||
|
||||
if err != nil {
|
||||
return eval.Memory{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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) {
|
||||
case eval.Number:
|
||||
case *eval.Number:
|
||||
memory.Offset = int8(index.Number)
|
||||
case eval.Register:
|
||||
case *eval.Register:
|
||||
memory.OffsetRegister = index.Register
|
||||
default:
|
||||
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)
|
||||
|
||||
if isArray {
|
||||
value := eval.Memory{
|
||||
value := &eval.Memory{
|
||||
Typ: array.Of,
|
||||
Memory: memory,
|
||||
}
|
||||
@ -63,7 +63,7 @@ func (f *Function) EvaluateArray(expr *expression.Expression) (eval.Memory, erro
|
||||
pointer, isPointer := base.Value.Typ.(*types.Pointer)
|
||||
|
||||
if isPointer {
|
||||
value := eval.Memory{
|
||||
value := &eval.Memory{
|
||||
Typ: pointer.To,
|
||||
Memory: memory,
|
||||
}
|
||||
|
@ -6,14 +6,14 @@ import (
|
||||
)
|
||||
|
||||
// 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)
|
||||
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
|
||||
value := eval.Memory{
|
||||
value := &eval.Memory{
|
||||
Typ: field.Type,
|
||||
Memory: asm.Memory{
|
||||
Base: variable.Value.Register,
|
||||
@ -51,7 +51,7 @@ func (f *Function) EvaluateDot(expr *expression.Expression) (eval.Value, error)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
value := eval.Number{
|
||||
value := &eval.Number{
|
||||
Typ: types.AnyInt,
|
||||
Number: number,
|
||||
}
|
||||
@ -65,7 +65,7 @@ func (f *Function) EvaluateDot(expr *expression.Expression) (eval.Value, error)
|
||||
if exists {
|
||||
f.File.Imports[leftText].Used = true
|
||||
|
||||
value := eval.Label{
|
||||
value := &eval.Label{
|
||||
Typ: types.AnyPointer,
|
||||
Label: function.UniqueName,
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ func (f *Function) EvaluateToken(t token.Token) (eval.Value, error) {
|
||||
name := t.Text(f.File.Bytes)
|
||||
|
||||
if name == "true" {
|
||||
value := eval.Number{
|
||||
value := &eval.Number{
|
||||
Typ: types.Bool,
|
||||
Number: 1,
|
||||
}
|
||||
@ -25,7 +25,7 @@ func (f *Function) EvaluateToken(t token.Token) (eval.Value, error) {
|
||||
}
|
||||
|
||||
if name == "false" {
|
||||
value := eval.Number{
|
||||
value := &eval.Number{
|
||||
Typ: types.Bool,
|
||||
Number: 0,
|
||||
}
|
||||
@ -37,11 +37,11 @@ func (f *Function) EvaluateToken(t token.Token) (eval.Value, error) {
|
||||
|
||||
if variable != nil {
|
||||
f.UseVariable(variable)
|
||||
return variable.Value, nil
|
||||
return &variable.Value, nil
|
||||
}
|
||||
|
||||
if function != nil {
|
||||
value := eval.Label{
|
||||
value := &eval.Label{
|
||||
Typ: types.AnyPointer,
|
||||
Label: function.UniqueName,
|
||||
}
|
||||
@ -58,7 +58,7 @@ func (f *Function) EvaluateToken(t token.Token) (eval.Value, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
value := eval.Number{
|
||||
value := &eval.Number{
|
||||
Typ: types.AnyInt,
|
||||
Number: number,
|
||||
}
|
||||
@ -74,7 +74,7 @@ func (f *Function) EvaluateToken(t token.Token) (eval.Value, error) {
|
||||
copy(slice[8:], data)
|
||||
label := f.AddBytes(slice)
|
||||
|
||||
value := eval.Label{
|
||||
value := &eval.Label{
|
||||
Typ: types.String,
|
||||
Label: label,
|
||||
}
|
||||
|
@ -8,16 +8,16 @@ import (
|
||||
// ValueToMemory moves a value into a memory region.
|
||||
func (f *Function) ValueToMemory(value eval.Value, memory asm.Memory) {
|
||||
switch value := value.(type) {
|
||||
case eval.Number:
|
||||
case *eval.Number:
|
||||
f.MemoryNumber(asm.STORE, memory, value.Number)
|
||||
case eval.Register:
|
||||
case *eval.Register:
|
||||
f.MemoryRegister(asm.STORE, memory, value.Register)
|
||||
case eval.Memory:
|
||||
case *eval.Memory:
|
||||
tmp := f.NewRegister()
|
||||
f.MemoryRegister(asm.LOAD, value.Memory, tmp)
|
||||
f.MemoryRegister(asm.STORE, memory, tmp)
|
||||
f.FreeRegister(tmp)
|
||||
case eval.Label:
|
||||
case *eval.Label:
|
||||
f.MemoryLabel(asm.STORE, memory, value.Label)
|
||||
}
|
||||
}
|
||||
|
@ -9,13 +9,13 @@ import (
|
||||
// ValueToRegister moves a value into a register.
|
||||
func (f *Function) ValueToRegister(value eval.Value, register cpu.Register) {
|
||||
switch value := value.(type) {
|
||||
case eval.Number:
|
||||
case *eval.Number:
|
||||
f.RegisterNumber(asm.MOVE, register, value.Number)
|
||||
case eval.Register:
|
||||
case *eval.Register:
|
||||
f.RegisterRegister(asm.MOVE, register, value.Register)
|
||||
case eval.Memory:
|
||||
case *eval.Memory:
|
||||
f.MemoryRegister(asm.LOAD, value.Memory, register)
|
||||
case eval.Label:
|
||||
case *eval.Label:
|
||||
f.RegisterLabel(asm.MOVE, register, value.Label)
|
||||
}
|
||||
}
|
||||
|
@ -8,10 +8,10 @@ type Label struct {
|
||||
Label string
|
||||
}
|
||||
|
||||
func (v Label) String() string {
|
||||
func (v *Label) String() string {
|
||||
return "Label"
|
||||
}
|
||||
|
||||
func (v Label) Type() types.Type {
|
||||
func (v *Label) Type() types.Type {
|
||||
return v.Typ
|
||||
}
|
||||
|
@ -11,10 +11,10 @@ type Memory struct {
|
||||
Memory asm.Memory
|
||||
}
|
||||
|
||||
func (v Memory) String() string {
|
||||
func (v *Memory) String() string {
|
||||
return "Memory"
|
||||
}
|
||||
|
||||
func (v Memory) Type() types.Type {
|
||||
func (v *Memory) Type() types.Type {
|
||||
return v.Typ
|
||||
}
|
||||
|
@ -8,10 +8,10 @@ type Number struct {
|
||||
Number int
|
||||
}
|
||||
|
||||
func (v Number) String() string {
|
||||
func (v *Number) String() string {
|
||||
return "Number"
|
||||
}
|
||||
|
||||
func (v Number) Type() types.Type {
|
||||
func (v *Number) Type() types.Type {
|
||||
return v.Typ
|
||||
}
|
||||
|
@ -12,10 +12,24 @@ type Register struct {
|
||||
Register cpu.Register
|
||||
}
|
||||
|
||||
func (v Register) String() string {
|
||||
func (v *Register) String() string {
|
||||
return "Register"
|
||||
}
|
||||
|
||||
func (v Register) Type() types.Type {
|
||||
func (v *Register) Type() types.Type {
|
||||
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
|
||||
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