Skip to content

Commit

Permalink
Implement set/get bit/byte
Browse files Browse the repository at this point in the history
  • Loading branch information
algorandskiy authored and pzbitskiy committed Jun 29, 2021
1 parent 6febebd commit 1f1da04
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 0 deletions.
8 changes: 8 additions & 0 deletions TealangLexer.l4
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ BUILTINFUNC
| BTOI
| SUBSTRING
| CONCAT
| GETBIT
| GETBYTE
| SETBIT
| SETBYTE
;

MAINFUNC
Expand Down Expand Up @@ -215,6 +219,10 @@ BTOI : 'btoi' ;
SUBSTRING : 'substring' ;
CONCAT : 'concat' ;
ASSERT : 'assert' ;
GETBIT : 'getbit' ;
GETBYTE : 'getbyte' ;
SETBIT : 'setbit' ;
SETBYTE : 'setbyte' ;

MULW : 'mulw' ;
ADDW : 'addw' ;
Expand Down
16 changes: 16 additions & 0 deletions compiler/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,14 @@ var builtinFun = map[string]bool{
"asset_holding_get": true,
"asset_params_get": true,
"assert": true,
"getbit": true,
"getbyte": true,
"setbit": true,
"setbyte": true,
}

var builtinFunDependantTypes = map[string]int{
"setbit": 0, // op type matches to first arg type
}

// TreeNodeIf represents a node in AST
Expand Down Expand Up @@ -755,6 +763,14 @@ func (n *funCallNode) getType() (exprType, error) {
var tp exprType
if builtin {
tp, err = opTypeFromSpec(n.name, 0)
if tp == unknownType {
if idx, ok := builtinFunDependantTypes[n.name]; ok {
tp, err = n.childrenNodes[idx].(ExprNodeIf).getType()
if err != nil {
return invalidType, fmt.Errorf("function %s type deduction failed: %s", n.name, err.Error())
}
}
}
} else {
tp, err = determineBlockReturnType(n.definition, []exprType{})
}
Expand Down
90 changes: 90 additions & 0 deletions compiler/codegen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -906,3 +906,93 @@ end_main:
CompareTEAL(a, expected, actual)

}

func TestCodegenGetSetBitByte(t *testing.T) {
a := require.New(t)

source := `
function approval() {
let a = getbit(255, 1)
let b = getbit("\xFF", 2)
let c = getbyte("test", 0)
return a + b + c
}
`
result, errors := Parse(source)
a.NotEmpty(result, errors)
a.Empty(errors)
actual := Codegen(result)
expected := `#pragma version *
intcblock 0 1 255 2
bytecblock 0xff 0x74657374
intc 2
intc 1
getbit
store 0
bytec 0
intc 3
getbit
store 1
bytec 1
intc 0
getbyte
store 2
load 0
load 1
+
load 2
+
return
end_main:
`
CompareTEAL(a, expected, actual)

source = `
function approval() {
let a = setbit(0, 1, 1)
let b = setbit("\xFF", 1, 0)
let c = setbyte("test", 0, 32)
let d = btoi(b)
let e = btoi(c)
return a + d + e
}
`
result, errors = Parse(source)
a.NotEmpty(result, errors)
a.Empty(errors)
actual = Codegen(result)
expected = `#pragma version *
intcblock 0 1 32
bytecblock 0xff 0x74657374
intc 0
intc 1
intc 1
setbit
store 0
bytec 0
intc 1
intc 0
setbit
store 1
bytec 1
intc 0
intc 2
setbyte
store 2
load 1
btoi
store 3
load 2
btoi
store 4
load 0
load 3
+
load 4
+
return
end_main:
`
CompareTEAL(a, expected, actual)

}

0 comments on commit 1f1da04

Please sign in to comment.