Skip to content

Commit

Permalink
Simplify ast structure
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigo-pino committed Sep 15, 2023
1 parent 84165f7 commit c90023d
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 143 deletions.
52 changes: 23 additions & 29 deletions pkg/assembler/assembler.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func encodeCasmProgram(casmAst CasmProgram) ([]*f.Element, error) {

func encodeInstruction(bytecode []*f.Element, instruction Instruction) ([]*f.Element, error) {
var encode uint64 = 0
expression := instruction.Unwrap().Expression()
expression := instruction.Expression()

encode, err := encodeDstReg(&instruction, encode)
if err != nil {
Expand Down Expand Up @@ -101,29 +101,29 @@ func encodeInstruction(bytecode []*f.Element, instruction Instruction) ([]*f.Ele
}

func encodeDstReg(instr *Instruction, encode uint64) (uint64, error) {
if instr.ApPlus != nil || instr.Core.Jump != nil {
if instr.ApPlus != nil || instr.Jump != nil {
// dstOffset is not involved so it is set to fp - 1 as default value
encode |= 1 << dstRegBit
encode |= uint64(biasedMinusOne)
return encode, nil
}
if instr.Core.Call != nil {
if instr.Call != nil {
// dstOffset is set to ap + 0
encode |= uint64(biasedZero)
return encode, nil
}
if instr.Core.Ret != nil {
if instr.Ret != nil {
// dstOffset is set as fp - 2
encode |= 1 << dstRegBit
encode |= uint64(biasedMinusTwo)
return encode, nil
}

var deref *Deref
if instr.Core.AssertEq != nil {
deref = instr.Core.AssertEq.Dst
} else if instr.Core.Jnz != nil {
deref = instr.Core.Jnz.Condition
if instr.AssertEq != nil {
deref = instr.AssertEq.Dst
} else if instr.Jnz != nil {
deref = instr.Jnz.Condition
}

biasedOffset, err := deref.BiasedOffset()
Expand All @@ -140,12 +140,12 @@ func encodeDstReg(instr *Instruction, encode uint64) (uint64, error) {
}

func encodeOp0Reg(instr *Instruction, expr Expressioner, encode uint64) (uint64, error) {
if instr.Core != nil && instr.Core.Call != nil {
if instr != nil && instr.Call != nil {
// op0 is set as [ap + 1] to store current pc
encode |= uint64(biasedPlusOne) << op0Offset
return encode, nil
}
if (instr.Core != nil && (instr.Core.Jnz != nil || instr.Core.Ret != nil)) ||
if (instr != nil && (instr.Jnz != nil || instr.Ret != nil)) ||
(expr.AsDeref() != nil || expr.AsImmediate() != nil) {
// op0 is not involved, it is set as fp - 1 as default value
encode |= 1 << op0RegBit
Expand Down Expand Up @@ -175,7 +175,7 @@ func encodeOp0Reg(instr *Instruction, expr Expressioner, encode uint64) (uint64,
// Given the expression and the current encode returns an updated encode with the corresponding bit
// and offset of op1, an immeadiate if exists, and a possible error
func encodeOp1Source(inst *Instruction, expr Expressioner, encode uint64) (uint64, *f.Element, error) {
if inst.Core != nil && inst.Core.Ret != nil {
if inst != nil && inst.Ret != nil {
// op1 is set as [fp - 1], where we read the previous pc
encode |= uint64(biasedMinusOne) << op1Offset
encode |= 1 << op1FpBit
Expand Down Expand Up @@ -226,25 +226,21 @@ func encodeResLogic(expression Expressioner, encode uint64) uint64 {
}

func encodePcUpdate(instruction Instruction, encode uint64) uint64 {
if instruction.Core == nil {
return encode
}

if instruction.Core.Jump != nil || instruction.Core.Call != nil {
if instruction.Jump != nil || instruction.Call != nil {
var isAbs bool
if instruction.Core.Jump != nil {
isAbs = instruction.Core.Jump.JumpType == "abs"
if instruction.Jump != nil {
isAbs = instruction.Jump.JumpType == "abs"
} else {
isAbs = instruction.Core.Call.CallType == "abs"
isAbs = instruction.Call.CallType == "abs"
}
if isAbs {
encode |= 1 << pcJumpAbsBit
} else {
encode |= 1 << pcJumpRelBit
}
} else if instruction.Core.Jnz != nil {
} else if instruction.Jnz != nil {
encode |= 1 << pcJnzBit
} else if instruction.Core.Ret != nil {
} else if instruction.Ret != nil {
encode |= 1 << pcJumpAbsBit
}

Expand All @@ -261,14 +257,12 @@ func encodeApUpdate(instruction Instruction, encode uint64) uint64 {
}

func encodeOpCode(instruction Instruction, encode uint64) uint64 {
if instruction.Core != nil {
if instruction.Core.Call != nil {
encode |= 1 << opcodeCallBit
} else if instruction.Core.Ret != nil {
encode |= 1 << opcodeRetBit
} else if instruction.Core.AssertEq != nil {
encode |= 1 << opcodeAssertEqBit
}
if instruction.Call != nil {
encode |= 1 << opcodeCallBit
} else if instruction.Ret != nil {
encode |= 1 << opcodeRetBit
} else if instruction.AssertEq != nil {
encode |= 1 << opcodeAssertEqBit
}
return encode
}
69 changes: 22 additions & 47 deletions pkg/assembler/grammar.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,13 @@ type CasmProgram struct {
}

type Instruction struct {
Core *CoreInstruction `@@`
ApPlusOne bool `( "," @"ap" "+" "+" )? ";" |`
ApPlus *ApPlus `@@ ";"`
}

type CoreInstruction struct {
AssertEq *AssertEq `@@ |`
Jnz *Jnz `@@ |`
Jump *Jump `@@ |`
Call *Call `@@ |`
Ret *Ret `@@ `
AssertEq *AssertEq `( @@ |`
Jnz *Jnz ` @@ |`
Jump *Jump ` @@ )`
ApPlusOne bool `( "," @"ap" "+" "+" )? ";" |`
Call *Call `( @@ |`
Ret *Ret ` @@ |`
ApPlus *ApPlus ` @@ ) ";"`
}

type AssertEq struct {
Expand Down Expand Up @@ -92,45 +88,24 @@ type CoreInstructioner interface {
Expression() Expressioner
}

func (instruction Instruction) Unwrap() CoreInstructioner {
if instruction.ApPlus != nil {
return instruction.ApPlus
} else if instruction.Core.AssertEq != nil {
return instruction.Core.AssertEq
} else if instruction.Core.Jump != nil {
return instruction.Core.Jump
} else if instruction.Core.Jnz != nil {
return instruction.Core.Jnz
} else if instruction.Core.Call != nil {
return instruction.Core.Call
} else {
return instruction.Core.Ret
func (instruction Instruction) Expression() Expressioner {
switch {
case instruction.AssertEq != nil:
return instruction.AssertEq.Value
case instruction.Jump != nil:
return instruction.Jump.Value
case instruction.Jnz != nil:
return instruction.Jnz.Value
case instruction.Call != nil:
return instruction.Call.Value
case instruction.ApPlus != nil:
return instruction.ApPlus.Value
default:
// when instruction is Ret
return nil
}
}

func (assertEq *AssertEq) Expression() Expressioner {
return assertEq.Value
}

func (jump *Jump) Expression() Expressioner {
return jump.Value
}

func (jnz *Jnz) Expression() Expressioner {
return jnz.Value
}

func (call *Call) Expression() Expressioner {
return call.Value
}

func (ret *Ret) Expression() Expressioner {
return nil
}
func (apPlus *ApPlus) Expression() Expressioner {
return apPlus.Value
}

type Expressioner interface {
AsDeref() *Deref
AsDoubleDeref() *DoubleDeref
Expand Down
122 changes: 55 additions & 67 deletions pkg/assembler/grammar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,20 @@ func TestAssertEqualWithRegisterGrammar(t *testing.T) {
&CasmProgram{
[]Instruction{
{
Core: &CoreInstruction{
AssertEq: &AssertEq{
Dst: &Deref{
Name: "fp",
AssertEq: &AssertEq{
Dst: &Deref{
Name: "fp",
Offset: &Offset{
Sign: "+",
Value: ptrOf(3),
},
},
Value: &Expression{
Deref: &Deref{
Name: "ap",
Offset: &Offset{
Sign: "+",
Value: ptrOf(3),
},
},
Value: &Expression{
Deref: &Deref{
Name: "ap",
Offset: &Offset{
Sign: "+",
Value: ptrOf(4),
},
Value: ptrOf(4),
},
},
},
Expand All @@ -56,22 +54,20 @@ func TestAssertEqualWithApPlusGrammar(t *testing.T) {
&CasmProgram{
[]Instruction{
{
Core: &CoreInstruction{
AssertEq: &AssertEq{
Dst: &Deref{
Name: "fp",
AssertEq: &AssertEq{
Dst: &Deref{
Name: "fp",
Offset: &Offset{
Sign: "+",
Value: ptrOf(3),
},
},
Value: &Expression{
Deref: &Deref{
Name: "ap",
Offset: &Offset{
Sign: "+",
Value: ptrOf(3),
},
},
Value: &Expression{
Deref: &Deref{
Name: "ap",
Offset: &Offset{
Sign: "+",
Value: ptrOf(4),
},
Value: ptrOf(4),
},
},
},
Expand All @@ -95,19 +91,17 @@ func TestAssertEqualWithImmediateGrammar(t *testing.T) {
&CasmProgram{
[]Instruction{
{
Core: &CoreInstruction{
AssertEq: &AssertEq{
Dst: &Deref{
Name: "fp",
Offset: &Offset{
Sign: "+",
Value: ptrOf(1),
},
},
Value: &Expression{
Immediate: ptrOf("5"),
AssertEq: &AssertEq{
Dst: &Deref{
Name: "fp",
Offset: &Offset{
Sign: "+",
Value: ptrOf(1),
},
},
Value: &Expression{
Immediate: ptrOf("5"),
},
},
ApPlusOne: false,
},
Expand All @@ -128,26 +122,24 @@ func TestAssertEqualWithMathOperationGrammar(t *testing.T) {
&CasmProgram{
[]Instruction{
{
Core: &CoreInstruction{
AssertEq: &AssertEq{
Dst: &Deref{
Name: "ap",
Offset: nil,
},
Value: &Expression{
MathOperation: &MathOperation{
Lhs: &Deref{
Name: "fp",
Offset: &Offset{
Sign: "+",
Value: ptrOf(7),
},
},
Operator: "+",
Rhs: &DerefOrImm{
Immediate: ptrOf("5"),
AssertEq: &AssertEq{
Dst: &Deref{
Name: "ap",
Offset: nil,
},
Value: &Expression{
MathOperation: &MathOperation{
Lhs: &Deref{
Name: "fp",
Offset: &Offset{
Sign: "+",
Value: ptrOf(7),
},
},
Operator: "+",
Rhs: &DerefOrImm{
Immediate: ptrOf("5"),
},
},
},
},
Expand All @@ -170,12 +162,10 @@ func TestCallAbsGrammar(t *testing.T) {
&CasmProgram{
[]Instruction{
{
Core: &CoreInstruction{
Call: &Call{
CallType: "abs",
Value: &DerefOrImm{
Immediate: ptrOf("123"),
},
Call: &Call{
CallType: "abs",
Value: &DerefOrImm{
Immediate: ptrOf("123"),
},
},
ApPlusOne: false,
Expand All @@ -197,10 +187,8 @@ func TestRetGrammar(t *testing.T) {
&CasmProgram{
[]Instruction{
{
Core: &CoreInstruction{
Ret: &Ret{
Ret: "",
},
Ret: &Ret{
Ret: "",
},
ApPlusOne: false,
},
Expand Down

0 comments on commit c90023d

Please sign in to comment.