(defpackage #:sarcasm.ast (:use #:cl) (:import-from #:sarcasm.util #:def/class) (:local-nicknames (#:a #:alexandria-2) (#:util #:sarcasm.util))) (in-package #:sarcasm.ast) ;;; TYPES (deftype i32 () '(integer 0 #.(expt 2 32))) (deftype i64 () '(integer 0 #. (expt 2 64))) (deftype f32 () 'single-float) (deftype f64 () 'double-float) (deftype numtype () '(or i32 i64 f32 f64)) (deftype typeidx () 'i32) (deftype vectype () '(bit-vector 128)) (deftype funcref () 't) (deftype externref () 't) (deftype reftype () '(or funcref externref)) (deftype valtype () '(or numtype vectype reftype)) (defun stack-effect-type-p (thing) "A stack effect type is a two element list of lists of keywords. It describes the types of values consumed off the stack and returned to the stack by instructions." (and (listp thing) (= 2 (length thing)) (listp (first thing)) (listp (second thing)) (every #'keywordp (first thing)) (every #'keywordp (second thing)))) (deftype stack-effect-type () "This is not part of the standard grammar, but appears implicitly in the WASM table of instructions found https://webassembly.github.io/spec/core/appendix/index-instructions.html In the `Type` column." '(satisfies stack-effect-type-p)) ;;; MODULE-STRUCTURES (def/class instr () ((name :prefix :type keyword) (code :prefix :type (vector byte)) (type :prefix :type stack-effect-type))) (def/class numeric-instr (instr)) (def/class func () (type :prefix :type typeidx) (locals :type (vector valtype)) (body :prefix :type expr)) ;;; MODULES (def/class module () (types funcs tables mems globals elems datas imports exports :type vector :initform (vector)) (start :type (or null t) ; TODO: what is this value type? :initform nil))