Skip to content

Commit

Permalink
fix parsing of number as string
Browse files Browse the repository at this point in the history
  • Loading branch information
cicr99 committed Aug 15, 2024
1 parent a8e4458 commit efc0e7d
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 39 deletions.
75 changes: 49 additions & 26 deletions pkg/hintrunner/zero/hintparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package zero

import (
"fmt"
"math/big"

"github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter"
"github.com/NethermindEth/cairo-vm-go/pkg/utils"
"github.com/alecthomas/participle/v2"
"github.com/alecthomas/participle/v2/lexer"
"github.com/consensys/gnark-crypto/ecc/stark-curve/fp"
)

Expand All @@ -17,8 +19,20 @@ import (
// term => Exp | ProdExp
// prodExp => Exp * Exp
// exp => cellRef | deref | dderef | int
var (
basicLexer = lexer.MustSimple([]lexer.SimpleRule{
{"Number", `\d+`},
{"Ident", `[a-zA-Z_]\w*`},
{"Punct", `[-[!@#$%^&*()+_={}\|:;"'<,>.?/]|]`},
{"whitespace", `[ \t]+`},
})
parser = participle.MustBuild[IdentifierExp](
participle.Lexer(basicLexer),
participle.UseLookahead(20),
)
)

var parser *participle.Parser[IdentifierExp] = participle.MustBuild[IdentifierExp](participle.UseLookahead(20))
// var parser *participle.Parser[IdentifierExp] = participle.MustBuild[IdentifierExp](participle.UseLookahead(20))

type IdentifierExp struct {
DerefCastExp *DerefCastExp `@@ |`
Expand Down Expand Up @@ -57,10 +71,10 @@ type ProdExp struct {
}

type Expression struct {
IntExp *OffsetExp `@@ |`
CellRefExp *CellRefExp `@@ |`
DDerefExp *DDerefExp `@@ |`
DerefExp *DerefExp `@@ |`
DDerefExp *DDerefExp `@@`
CellRefExp *CellRefExp `@@ |`
IntExp *OffsetExp `@@`
}

type CellRefSimple struct {
Expand All @@ -80,8 +94,8 @@ type RegisterOffset struct {
}

type OffsetExp struct {
Number *int `@Int |`
NegNumber *int `"(" "-" @Int ")"`
Number string `@Number |`
NegNumber string `"(" "-" @Number ")"`
}

type DerefExp struct {
Expand All @@ -95,8 +109,8 @@ type DerefOffsetExp struct {
}

type DDerefExp struct {
DerefExp *DerefExp `"[" @@ "]" |`
DerefOffsetExp *DerefOffsetExp `"[" @@ "]"`
DerefOffsetExp *DerefOffsetExp `"[" @@ "]" |`
DerefExp *DerefExp `"[" @@ "]"`
}

// AST Functionality
Expand Down Expand Up @@ -129,8 +143,7 @@ func (expression DerefCastExp) Evaluate() (hinter.Reference, error) {
case hinter.BinaryOp:
if left, ok := result.Lhs.(hinter.Deref); ok {
if right, ok := result.Rhs.(hinter.Immediate); ok {
offset, err := utils.Int16FromFelt((*fp.Element)(&right))
if err == nil {
if offset, ok := utils.Int16FromFelt((*fp.Element)(&right)); ok {
return hinter.DoubleDeref{
Deref: left,
Offset: offset,
Expand Down Expand Up @@ -173,8 +186,7 @@ func (expression AddExp) Evaluate() (hinter.Reference, error) {
if rightResult, ok := rightExp.(hinter.Immediate); ok {
switch leftResult := leftExp.(type) {
case hinter.CellRefer:
off, err := utils.Int16FromFelt((*fp.Element)(&rightResult))
if err == nil {
if off, ok := utils.Int16FromFelt((*fp.Element)(&rightResult)); ok {
if expression.Operator == "-" {
off = -off
}
Expand Down Expand Up @@ -254,7 +266,7 @@ func (expression Expression) Evaluate() (hinter.Reference, error) {
if err != nil {
return nil, err
}
return hinter.Immediate(*new(fp.Element).SetInt64(int64(*intExp))), nil
return hinter.Immediate(*new(fp.Element).SetBigInt(intExp)), nil
case expression.CellRefExp != nil:
return expression.CellRefExp.Evaluate()
case expression.DerefExp != nil:
Expand Down Expand Up @@ -284,7 +296,10 @@ func (expression CellRefExp) Evaluate() (hinter.CellRefer, error) {

func (expression RegisterOffset) Evaluate() (hinter.CellRefer, error) {
offsetValue, _ := expression.Offset.Evaluate()
offset := int16(*offsetValue)
offset, ok := utils.Int16FromBigInt(offsetValue)
if !ok {
return nil, fmt.Errorf("offset does not fit in int16")
}
if expression.Operator == "-" {
offset = -offset
}
Expand All @@ -303,27 +318,32 @@ func EvaluateRegister(register string, offset int16) (hinter.CellRefer, error) {
}
}

func (expression OffsetExp) Evaluate() (*int, error) {
func (expression OffsetExp) Evaluate() (*big.Int, error) {
switch {
case expression.Number != nil:
return expression.Number, nil
case expression.NegNumber != nil:
negNumber := -*expression.NegNumber
return &negNumber, nil
case expression.Number != "":
bigIntValue, ok := new(big.Int).SetString(expression.Number, 10)
if !ok {
return nil, fmt.Errorf("expected a number")
}
return bigIntValue, nil
case expression.NegNumber != "":
bigIntValue, ok := new(big.Int).SetString(expression.NegNumber, 10)
if !ok {
return nil, fmt.Errorf("expected a number")
}
mod := fp.Modulus()
negNumber := new(big.Int).Sub(mod, bigIntValue)
return negNumber, nil
default:
return nil, fmt.Errorf("expected a number")
}
}

func (expression DerefExp) Evaluate() (hinter.Deref, error) {
cellRefExp, err := expression.CellRefExp.Evaluate()
cellRef, err := expression.CellRefExp.Evaluate()
if err != nil {
return hinter.Deref{}, err
}
cellRef, ok := cellRefExp.(hinter.CellRefer)
if !ok {
return hinter.Deref{}, fmt.Errorf("expected a CellRefer expression but got %s", cellRefExp)
}
return hinter.Deref{Deref: cellRef}, nil
}

Expand All @@ -347,7 +367,10 @@ func (expression DDerefExp) Evaluate() (hinter.DoubleDeref, error) {
if err != nil {
return hinter.DoubleDeref{}, err
}
offset := int16(*offsetValue)
offset, ok := utils.Int16FromBigInt(offsetValue)
if !ok {
return hinter.DoubleDeref{}, fmt.Errorf("offset does not fit in int16")
}
if expression.DerefOffsetExp.Operator == "-" {
offset = -offset
}
Expand Down
17 changes: 13 additions & 4 deletions pkg/hintrunner/zero/hintparser_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package zero

import (
"fmt"
"testing"

"github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter"
Expand Down Expand Up @@ -76,9 +75,9 @@ func TestHintParser(t *testing.T) {
},
},
{
Parameter: "cast(7, felt)",
Parameter: "cast(2389472938759290879897, felt)",
ExpectedCellRefer: nil,
ExpectedResOperander: hinter.Immediate(*feltInt64((7))),
ExpectedResOperander: hinter.Immediate(*feltString("2389472938759290879897")),
},
{
Parameter: "cast([[ap + 2] + (-5)], felt)",
Expand All @@ -90,11 +89,21 @@ func TestHintParser(t *testing.T) {
Offset: int16(-5),
},
},
{
Parameter: "cast([fp + (-4)] * 18, felt)",
ExpectedCellRefer: nil,
ExpectedResOperander: hinter.BinaryOp{
Operator: hinter.Mul,
Lhs: hinter.Deref{
Deref: hinter.FpCellRef(-4),
},
Rhs: hinter.Immediate(*feltInt64(18)),
},
},
}

for _, test := range testSet {
output, err := ParseIdentifier(test.Parameter)
fmt.Println(test.Parameter)
require.NoError(t, err)

if test.ExpectedCellRefer != nil {
Expand Down
21 changes: 12 additions & 9 deletions pkg/utils/math.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package utils

import (
"fmt"
"math"
"math/big"
"math/bits"
Expand Down Expand Up @@ -128,26 +127,30 @@ func FeltDivRem(a, b *fp.Element) (div fp.Element, rem fp.Element) {
return div, rem
}

func Int16FromFelt(n *fp.Element) (int16, error) {
func Int16FromFelt(n *fp.Element) (int16, bool) {
bigN := n.BigInt(new(big.Int))
return Int16FromBigInt(bigN)
}

func Int16FromBigInt(n *big.Int) (int16, bool) {
mod := fp.Modulus()
negN := new(big.Int).Sub(mod, bigN)
negN := new(big.Int).Sub(mod, n)
maxInt16 := new(big.Int).SetInt64(int64(math.MaxInt16))

var result int64
if bigN.Cmp(negN) == 1 {
if n.Cmp(negN) == 1 {
if negN.Cmp(maxInt16) == 1 {
return 0, fmt.Errorf("felt number does not fit in int16")
return 0, false
}
result = -negN.Int64()
} else {
if bigN.Cmp(maxInt16) == 1 {
return 0, fmt.Errorf("felt number does not fit in int16")
if n.Cmp(maxInt16) == 1 {
return 0, false
}
result = bigN.Int64()
result = n.Int64()
}

return int16(result), nil
return int16(result), true
}

func RightRot(value uint32, n uint32) uint32 {
Expand Down

0 comments on commit efc0e7d

Please sign in to comment.