return false
}
-func requireAllValuesDisposedOnce(contract *Contract, clause *Clause) error {
- err := valueDisposedOnce(contract.Value, clause)
- if err != nil {
- return err
- }
- return nil
-}
-
-func valueDisposedOnce(value ValueInfo, clause *Clause) error {
- var count int
- for _, stmt := range clause.statements {
- count = valueDisposedCount(value, stmt, count)
- }
- switch count {
- case -1:
- return fmt.Errorf("valueAmount \"%s\" and valueAsset \"%s\" used times is not equal between if and else statement in clause \"%s\"",
- value.Amount, value.Asset, clause.Name)
- case 0:
- return fmt.Errorf("valueAmount \"%s\" or valueAsset \"%s\" not disposed in clause \"%s\"", value.Amount, value.Asset, clause.Name)
- case 1:
- return nil
- default:
- return fmt.Errorf("valueAmount \"%s\" or valueAsset \"%s\" disposed multiple times in clause \"%s\"", value.Amount, value.Asset, clause.Name)
- }
-}
-
-func valueDisposedCount(value ValueInfo, stat statement, count int) int {
- switch stmt := stat.(type) {
- case *ifStatement:
- var trueCount int
- var falseCount int
- for _, trueStmt := range stmt.body.trueBody {
- trueCount = valueDisposedCount(value, trueStmt, count)
- }
-
- for _, falseStmt := range stmt.body.falseBody {
- falseCount = valueDisposedCount(value, falseStmt, count)
- }
-
- if trueCount != falseCount {
- return -1
- }
- count = trueCount
-
- case *unlockStatement:
- if references(stmt.unlockedAmount, value.Amount) && references(stmt.unlockedAsset, value.Asset) {
- count++
- }
- case *lockStatement:
- if references(stmt.lockedAmount, value.Amount) && references(stmt.lockedAsset, value.Asset) {
- count++
- }
- }
-
- return count
-}
-
func referencedBuiltin(expr expression) *builtin {
if v, ok := expr.(varRef); ok {
for _, b := range builtins {
}
}
- err = requireAllValuesDisposedOnce(contract, clause)
- if err != nil {
- return err
- }
err = typeCheckClause(contract, clause, env)
if err != nil {
return err
}
lType := e.left.typ(env)
- if e.op.left != "" && !(lType == e.op.left || lType == amountType) {
+ if e.op.left != "" && ((e.op.left == intType && !(lType == amountType || lType == intType)) ||
+ (e.op.left == boolType && !(lType == boolType))) {
return stk, fmt.Errorf("in \"%s\", left operand has type \"%s\", must be \"%s\"", e, lType, e.op.left)
}
rType := e.right.typ(env)
- if e.op.right != "" && !(rType == e.op.right || rType == amountType) {
+ if e.op.right != "" && ((e.op.right == intType && !(rType == amountType || rType == intType)) ||
+ (e.op.right == boolType && !(rType == boolType))) {
return stk, fmt.Errorf("in \"%s\", right operand has type \"%s\", must be \"%s\"", e, rType, e.op.right)
}
for i := len(e.args) - 1; i >= 0; i-- {
arg := e.args[i]
- if entry.c.Params[i].Type != "" && arg.typ(env) != entry.c.Params[i].Type {
+ if entry.c.Params[i].Type != "" && arg.typ(env) != entry.c.Params[i].Type &&
+ !(arg.typ(env) == intType && entry.c.Params[i].Type == amountType) {
return stk, fmt.Errorf("argument %d to contract \"%s\" has type \"%s\", must be \"%s\"", i, entry.c.Name, arg.typ(env), entry.c.Params[i].Type)
}
stk, err = compileExpr(b, stk, contract, clause, env, counts, arg)