forked from cerc-io/plugeth
Moved assembler stage to the mutan compiler
This commit is contained in:
parent
bf850974f3
commit
21f8806eed
193
ethutil/asm.go
193
ethutil/asm.go
@ -1,193 +0,0 @@
|
||||
package ethutil
|
||||
|
||||
import (
|
||||
_ "fmt"
|
||||
"math/big"
|
||||
_ "regexp"
|
||||
)
|
||||
|
||||
// Op codes
|
||||
var OpCodes = map[string]byte{
|
||||
// 0x0 range - arithmetic ops
|
||||
"STOP": 0x00,
|
||||
"ADD": 0x01,
|
||||
"MUL": 0x02,
|
||||
"SUB": 0x03,
|
||||
"DIV": 0x04,
|
||||
"SDIV": 0x05,
|
||||
"MOD": 0x06,
|
||||
"SMOD": 0x07,
|
||||
"EXP": 0x08,
|
||||
"NEG": 0x09,
|
||||
"LT": 0x0a,
|
||||
"GT": 0x0b,
|
||||
"EQ": 0x0c,
|
||||
"NOT": 0x0d,
|
||||
|
||||
// 0x10 range - bit ops
|
||||
"AND": 0x10,
|
||||
"OR": 0x11,
|
||||
"XOR": 0x12,
|
||||
"BYTE": 0x13,
|
||||
|
||||
// 0x20 range - crypto
|
||||
"SHA3": 0x20,
|
||||
|
||||
// 0x30 range - closure state
|
||||
"ADDRESS": 0x30,
|
||||
"BALANCE": 0x31,
|
||||
"ORIGIN": 0x32,
|
||||
"CALLER": 0x33,
|
||||
"CALLVALUE": 0x34,
|
||||
"CALLDATALOAD": 0x35,
|
||||
"CALLDATASIZE": 0x36,
|
||||
"GASPRICE": 0x38,
|
||||
|
||||
// 0x40 range - block operations
|
||||
"PREVHASH": 0x40,
|
||||
"COINBASE": 0x41,
|
||||
"TIMESTAMP": 0x42,
|
||||
"NUMBER": 0x43,
|
||||
"DIFFICULTY": 0x44,
|
||||
"GASLIMIT": 0x45,
|
||||
|
||||
// 0x50 range - 'storage' and execution
|
||||
"PUSH": 0x50,
|
||||
|
||||
"PUSH20": 0x80,
|
||||
|
||||
"POP": 0x51,
|
||||
"DUP": 0x52,
|
||||
"SWAP": 0x53,
|
||||
"MLOAD": 0x54,
|
||||
"MSTORE": 0x55,
|
||||
"MSTORE8": 0x56,
|
||||
"SLOAD": 0x57,
|
||||
"SSTORE": 0x58,
|
||||
"JUMP": 0x59,
|
||||
"JUMPI": 0x5a,
|
||||
"PC": 0x5b,
|
||||
"MSIZE": 0x5c,
|
||||
|
||||
// 0x60 range - closures
|
||||
"CREATE": 0x60,
|
||||
"CALL": 0x61,
|
||||
"RETURN": 0x62,
|
||||
|
||||
// 0x70 range - other
|
||||
"LOG": 0x70,
|
||||
"SUICIDE": 0x7f,
|
||||
}
|
||||
|
||||
// Is op code
|
||||
//
|
||||
// Check whether the given string matches anything in
|
||||
// the OpCode list
|
||||
func IsOpCode(s string) bool {
|
||||
for key, _ := range OpCodes {
|
||||
if key == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Compile instruction
|
||||
//
|
||||
// Attempts to compile and parse the given instruction in "s"
|
||||
// and returns the byte sequence
|
||||
func CompileInstr(s interface{}) ([]byte, error) {
|
||||
switch s.(type) {
|
||||
case string:
|
||||
str := s.(string)
|
||||
isOp := IsOpCode(str)
|
||||
if isOp {
|
||||
return []byte{OpCodes[str]}, nil
|
||||
}
|
||||
|
||||
num := new(big.Int)
|
||||
_, success := num.SetString(str, 0)
|
||||
// Assume regular bytes during compilation
|
||||
if !success {
|
||||
num.SetBytes([]byte(str))
|
||||
} else {
|
||||
// tmp fix for 32 bytes
|
||||
n := BigToBytes(num, 256)
|
||||
return n, nil
|
||||
}
|
||||
|
||||
return num.Bytes(), nil
|
||||
case int:
|
||||
num := BigToBytes(big.NewInt(int64(s.(int))), 256)
|
||||
return num, nil
|
||||
case []byte:
|
||||
return BigD(s.([]byte)).Bytes(), nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Assemble
|
||||
//
|
||||
// Assembles the given instructions and returns EVM byte code
|
||||
func Assemble(instructions ...interface{}) (script []byte) {
|
||||
//script = make([]string, len(instructions))
|
||||
|
||||
for _, val := range instructions {
|
||||
instr, _ := CompileInstr(val)
|
||||
|
||||
//script[i] = string(instr)
|
||||
script = append(script, instr...)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Pre process script
|
||||
//
|
||||
// Take data apart and attempt to find the "init" section and
|
||||
// "main" section. `main { } init { }`
|
||||
func PreProcess(data string) (mainInput, initInput string) {
|
||||
mainInput = getCodeSectionFor("main", data)
|
||||
if mainInput == "" {
|
||||
mainInput = data
|
||||
}
|
||||
initInput = getCodeSectionFor("init", data)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Very, very dumb parser. Heed no attention :-)
|
||||
func getCodeSectionFor(blockMatcher, input string) string {
|
||||
curCount := -1
|
||||
length := len(blockMatcher)
|
||||
matchfst := rune(blockMatcher[0])
|
||||
var currStr string
|
||||
|
||||
for i, run := range input {
|
||||
// Find init
|
||||
if curCount == -1 && run == matchfst && input[i:i+length] == blockMatcher {
|
||||
curCount = 0
|
||||
} else if curCount > -1 {
|
||||
if run == '{' {
|
||||
curCount++
|
||||
if curCount == 1 {
|
||||
continue
|
||||
}
|
||||
} else if run == '}' {
|
||||
curCount--
|
||||
if curCount == 0 {
|
||||
// we are done
|
||||
curCount = -1
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if curCount > 0 {
|
||||
currStr += string(run)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return currStr
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package ethutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPreProcess(t *testing.T) {
|
||||
main, init := PreProcess(`
|
||||
init {
|
||||
// init
|
||||
if a > b {
|
||||
if {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main {
|
||||
// main
|
||||
if a > b {
|
||||
if c > d {
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
fmt.Println("main")
|
||||
fmt.Println(main)
|
||||
fmt.Println("init")
|
||||
fmt.Println(init)
|
||||
}
|
Loading…
Reference in New Issue
Block a user