-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Code cleanup & further implementation
- Loading branch information
Showing
11 changed files
with
710 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#lang racket | ||
(require racket/cmdline "src/puff.rkt") | ||
|
||
(define filename "") | ||
|
||
(define compilation-output 'bytecode) | ||
|
||
(command-line | ||
#:program "puff" | ||
#:once-any | ||
[("-b" "--bytecode") "Output bytecode" (set! compilation-output 'bytecode)] | ||
[("-r" "--runtime-bytecode") "Output runtime bytecode" (set! compilation-output 'runtime)] | ||
#:args (f) | ||
(set! filename f)) | ||
|
||
(match compilation-output | ||
['bytecode (displayln (compile-filename filename))] | ||
['runtime (displayln (compile-filename-runtime filename))]) |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
#lang racket | ||
|
||
(require "lexer.rkt" | ||
"huffparser.rkt" | ||
"utils.rkt" | ||
threading) | ||
|
||
;; some structs, for convenience getter/setter methods | ||
;; program-data will contain all the data required to compile a contract | ||
(struct program-data (labels | ||
macros | ||
functions | ||
fndecls | ||
eventdefs | ||
errordefs | ||
constants | ||
errors | ||
includes | ||
ctx) #:mutable) | ||
|
||
;; no-arg constructor | ||
(define (make-program-data) | ||
(program-data (make-hash) | ||
(make-hash) | ||
(make-hash) | ||
(make-hash) | ||
(make-hash) | ||
(make-hash) | ||
(make-hash) | ||
(make-hash) | ||
(list) | ||
(make-hash))) | ||
|
||
;; not really needed, but a struct for a specific macro's data | ||
;; TODO: decide if we should get rid of this and just use the list | ||
(struct macro-data (args takes returns body)) | ||
|
||
;; constructor | ||
(define (make-macro-data defmacro) | ||
(apply macro-data defmacro)) | ||
|
||
|
||
;; analyze all top-level nodes, outputting into the same data object | ||
(define (analyze-program program data) | ||
(for-each (lambda (n) (analyze-node n data)) (rest program))) | ||
|
||
;; save each macro body in the data object | ||
(define (analyze-defmacro defmacro data) | ||
(match defmacro | ||
[(list 'defmacro identifier args takes returns body) (hash-set! (program-data-macros data) identifier (list args takes returns body))] | ||
[_ (error "Invalid defmacro")])) | ||
|
||
;; save each function body in the data object | ||
(define (analyze-defn defn data) | ||
(match defn | ||
[(list 'defn identifier args takes returns body) (hash-set! (program-data-functions data) identifier (list args takes returns body))] | ||
[_ (error "Invalid defn")])) | ||
|
||
;; save each constant value in the data object | ||
(define (analyze-defconst defconst data) | ||
(match defconst | ||
[(list 'defconst identifier value) (hash-set! (program-data-constants data) identifier value)] | ||
[_ (error "Invalid defconst")])) | ||
|
||
#| IMPORT HANDLING |# | ||
;; macro to save the current context and restore it after the analysis | ||
;; this is used for includes, which need to know the current file's directory | ||
;; so we temporarily set the context to one with the include's filename | ||
(define-syntax with-temp-context | ||
(syntax-rules () | ||
[(_ data ctx body ...) | ||
(let ([old-ctx (program-data-ctx data)]) | ||
(set-program-data-ctx! data ctx) | ||
(begin | ||
body ... | ||
(set-program-data-ctx! data old-ctx)))])) | ||
|
||
(define (analyze-filename filename data) | ||
(let ([parse-tree (~> filename | ||
file->string | ||
lex | ||
parse | ||
syntax->datum)]) | ||
(with-temp-context data (hash 'filename filename) | ||
(analyze-node parse-tree data)))) | ||
|
||
(define (analyze-include inc data) | ||
(let* ([current-file (hash-ref (program-data-ctx data) 'filename)] | ||
[current-dir (path->string (path-only (path->complete-path current-file)))]) | ||
(parameterize ([current-directory current-dir]) | ||
(match inc | ||
[(list 'include filename) (let* ([filename (string-append current-dir (format-filename filename))]) | ||
(set-program-data-includes! data (cons filename (program-data-includes data))) | ||
(analyze-filename filename data))] | ||
[_ (error "Invalid include")])))) | ||
#| END IMPORT HANDLING |# | ||
|
||
|
||
;; top-level node-handler function | ||
(define (analyze-node node [data #f] [ctx #f]) | ||
(let ([data (or data (make-program-data))]) | ||
(when ctx (set-program-data-ctx! data ctx)) | ||
(match (first node) | ||
['program (analyze-program node data)] | ||
['defmacro (analyze-defmacro node data)] | ||
['include (analyze-include node data)] | ||
['defconst (analyze-defconst node data)] | ||
['defn (analyze-defn node data)]) | ||
data)) | ||
|
||
(provide (struct-out program-data) | ||
(struct-out macro-data) | ||
make-program-data | ||
make-macro-data | ||
analyze-node) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
#lang racket | ||
|
||
#| | ||
This module provides a simple assembler for Ethereum Virtual Machine (EVM) opcodes. | ||
It provides a mapping from opcode names to their hexadecimal values, and functions | ||
to convert between opcode names and their hexadecimal values. | ||
The module also provides functions to convert between bytes and hexadecimal strings. | ||
|# | ||
|
||
(define opcode-map | ||
(hash "STOP" #x00 | ||
"ADD" #x01 | ||
"MUL" #x02 | ||
"SUB" #x03 | ||
"DIV" #x04 | ||
"SDIV" #x05 | ||
"MOD" #x06 | ||
"SMOD" #x07 | ||
"ADDMOD" #x08 | ||
"MULMOD" #x09 | ||
"EXP" #x0a | ||
"SIGNEXTEND" #x0b | ||
"LT" #x10 | ||
"GT" #x11 | ||
"SLT" #x12 | ||
"SGT" #x13 | ||
"EQ" #x14 | ||
"ISZERO" #x15 | ||
"AND" #x16 | ||
"OR" #x17 | ||
"XOR" #x18 | ||
"NOT" #x19 | ||
"BYTE" #x1a | ||
"SHL" #x1b | ||
"SHR" #x1c | ||
"SAR" #x1d | ||
"KECCAK256" #x20 | ||
"ADDRESS" #x30 | ||
"BALANCE" #x31 | ||
"ORIGIN" #x32 | ||
"CALLER" #x33 | ||
"CALLVALUE" #x34 | ||
"CALLDATALOAD" #x35 | ||
"CALLDATASIZE" #x36 | ||
"CALLDATACOPY" #x37 | ||
"CODESIZE" #x38 | ||
"CODECOPY" #x39 | ||
"GASPRICE" #x3a | ||
"EXTCODESIZE" #x3b | ||
"EXTCODECOPY" #x3c | ||
"RETURNDATASIZE" #x3d | ||
"RETURNDATACOPY" #x3e | ||
"EXTCODEHASH" #x3f | ||
"BLOCKHASH" #x40 | ||
"COINBASE" #x41 | ||
"TIMESTAMP" #x42 | ||
"NUMBER" #x43 | ||
"PREVRANDAO" #x44 | ||
"GASLIMIT" #x45 | ||
"CHAINID" #x46 | ||
"SELFBALANCE" #x47 | ||
"BASEFEE" #x48 | ||
"BLOBHASH" #x49 | ||
"BLOBBASEFEE" #x4a | ||
"POP" #x50 | ||
"MLOAD" #x51 | ||
"MSTORE" #x52 | ||
"MSTORE8" #x53 | ||
"SLOAD" #x54 | ||
"SSTORE" #x55 | ||
"JUMP" #x56 | ||
"JUMPI" #x57 | ||
"PC" #x58 | ||
"MSIZE" #x59 | ||
"GAS" #x5a | ||
"JUMPDEST" #x5b | ||
"TLOAD" #x5C | ||
"TSTORE" #x5D | ||
"MCOPY" #x5E | ||
"PUSH0" #x5F | ||
"PUSH1" #x60 | ||
"PUSH2" #x61 | ||
"PUSH3" #x62 | ||
"PUSH4" #x63 | ||
"PUSH5" #x64 | ||
"PUSH6" #x65 | ||
"PUSH7" #x66 | ||
"PUSH8" #x67 | ||
"PUSH9" #x68 | ||
"PUSH10" #x69 | ||
"PUSH11" #x6A | ||
"PUSH12" #x6B | ||
"PUSH13" #x6C | ||
"PUSH14" #x6D | ||
"PUSH15" #x6E | ||
"PUSH16" #x6F | ||
"PUSH17" #x70 | ||
"PUSH18" #x71 | ||
"PUSH19" #x72 | ||
"PUSH20" #x73 | ||
"PUSH21" #x74 | ||
"PUSH22" #x75 | ||
"PUSH23" #x76 | ||
"PUSH24" #x77 | ||
"PUSH25" #x78 | ||
"PUSH26" #x79 | ||
"PUSH27" #x7A | ||
"PUSH28" #x7B | ||
"PUSH29" #x7C | ||
"PUSH30" #x7D | ||
"PUSH31" #x7E | ||
"PUSH32" #x7F | ||
"DUP1" #x80 | ||
"DUP2" #x81 | ||
"DUP3" #x82 | ||
"DUP4" #x83 | ||
"DUP5" #x84 | ||
"DUP6" #x85 | ||
"DUP7" #x86 | ||
"DUP8" #x87 | ||
"DUP9" #x88 | ||
"DUP10" #x89 | ||
"DUP11" #x8A | ||
"DUP12" #x8B | ||
"DUP13" #x8C | ||
"DUP14" #x8D | ||
"DUP15" #x8E | ||
"DUP16" #x8F | ||
"SWAP1" #x90 | ||
"SWAP2" #x91 | ||
"SWAP3" #x92 | ||
"SWAP4" #x93 | ||
"SWAP5" #x94 | ||
"SWAP6" #x95 | ||
"SWAP7" #x96 | ||
"SWAP8" #x97 | ||
"SWAP9" #x98 | ||
"SWAP10" #x99 | ||
"SWAP11" #x9A | ||
"SWAP12" #x9B | ||
"SWAP13" #x9C | ||
"SWAP14" #x9D | ||
"SWAP15" #x9E | ||
"SWAP16" #x9F | ||
"LOG0" #xA0 | ||
"LOG1" #xA1 | ||
"LOG2" #xA2 | ||
"LOG3" #xA3 | ||
"LOG4" #xA4 | ||
"CREATE" #xF0 | ||
"CALL" #xF1 | ||
"CALLCODE" #xF2 | ||
"RETURN" #xF3 | ||
"DELEGATECALL" #xF4 | ||
"CREATE2" #xF5 | ||
"STATICCALL" #xFA | ||
"REVERT" #xFD | ||
"INVALID" #xFE | ||
"SELFDESTRUCT" #xFF)) | ||
|
||
(define opcodes (hash-keys opcode-map)) | ||
|
||
(define (byte->opcode) | ||
(let ([byte (read-byte)]) | ||
(hash-ref opcode-map byte))) | ||
|
||
(define (assemble-opcode opcode) | ||
(cond | ||
[(hash-has-key? opcode-map opcode) (hash-ref opcode-map opcode)] | ||
[(string-prefix? opcode "0x") (string->number (substring opcode 2) 16)] | ||
[else (error "Unknown opcode" opcode)])) | ||
|
||
(define (assemble-opcodes opcodes) | ||
(map assemble-opcode opcodes)) | ||
|
||
(provide opcode-map opcodes assemble-opcode assemble-opcodes) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#lang racket | ||
(require "huff-ops.rkt" | ||
"utils.rkt" | ||
threading) | ||
|
||
;; in this file: functions to generate actual opcodes | ||
;; this means: | ||
;; - huff instructions like mstore become "MSTORE" | ||
;; - hex values like "0x20" become "PUSH1 0x20" | ||
;; - constructor generators | ||
|
||
(define (handle-val val) | ||
(cond | ||
[(instruction? val) (list (instruction->opcode val))] | ||
[else (begin | ||
(displayln (format "Unknown value: ~a" val)) | ||
(list (string-upcase (symbol->string val))))])) | ||
|
||
(define (handle-hex val) | ||
(if (equal? val "0x00") | ||
(list "PUSH0") | ||
(let* ( | ||
[num-bytes (ceiling (/ (- (string-length val) 2) 2))] | ||
[push-instr (string-append "PUSH" (number->string num-bytes))]) | ||
(list push-instr val)))) | ||
|
||
(define (handle-expr expr) | ||
(match (first expr) | ||
['hex (handle-hex (second expr))] | ||
['const-ref (list expr)] | ||
['body (apply append (map handle-tree (rest expr)))])) | ||
|
||
(define (handle-tree tree) | ||
(if (list? tree) | ||
(handle-expr tree) | ||
(handle-val tree))) | ||
|
||
(define (generate-copy-constructor sz) | ||
(let ([sz-hex-str (string-append "0x" (number->string sz 16))]) | ||
(append (handle-hex sz-hex-str) '("DUP1" "PUSH1" "0x09" "RETURNDATASIZE" "CODECOPY" "RETURNDATASIZE" "RETURN")))) | ||
|
||
(provide handle-tree | ||
handle-hex | ||
handle-val | ||
generate-copy-constructor) |
Oops, something went wrong.