diff --git a/README.md b/README.md index 2f9c45f7..d58cf093 100644 --- a/README.md +++ b/README.md @@ -318,6 +318,11 @@ push(~a) ``` push(mem_addr) ``` +- `ref` - pushes the address of the top of the stack onto the stack. (Compilation-only) +``` +# This is not actually implemented in simulation mode +push(byref(stack[-1])) +``` - `.` - store a given byte at the address on the stack. ``` byte = pop() diff --git a/porth.py b/porth.py index 212dfbcc..51165f79 100755 --- a/porth.py +++ b/porth.py @@ -56,6 +56,7 @@ class Intrinsic(Enum): OVER=auto() ROT=auto() MEM=auto() + REF=auto() LOAD=auto() STORE=auto() FORTH_LOAD=auto() @@ -201,7 +202,7 @@ def simulate_little_endian_linux(program: Program, argv: List[str]): else: ip += 1 elif op.typ == OpType.INTRINSIC: - assert len(Intrinsic) == 41, "Exhaustive handling of intrinsic in simulate_little_endian_linux()" + assert len(Intrinsic) == 42, "Exhaustive handling of intrinsic in simulate_little_endian_linux()" if op.operand == Intrinsic.PLUS: a = stack.pop() b = stack.pop() @@ -314,6 +315,8 @@ def simulate_little_endian_linux(program: Program, argv: List[str]): elif op.operand == Intrinsic.MEM: stack.append(mem_buf_ptr) ip += 1 + elif op.operand == Intrinsic.REF: + assert False, "%s:%d:%d Stack pointers are not allowed in simulation mode." % op.token.loc elif op.operand == Intrinsic.LOAD: addr = stack.pop() byte = mem[addr] @@ -538,7 +541,7 @@ def type_check_program(program: Program): stack.append((DataType.INT, op.token)) stack.append((DataType.PTR, op.token)) elif op.typ == OpType.INTRINSIC: - assert len(Intrinsic) == 41, "Exhaustive intrinsic handling in type_check_program()" + assert len(Intrinsic) == 42, "Exhaustive intrinsic handling in type_check_program()" assert isinstance(op.operand, Intrinsic), "This could be a bug in compilation step" if op.operand == Intrinsic.PLUS: assert len(DataType) == 3, "Exhaustive type handling in PLUS intrinsic" @@ -802,6 +805,8 @@ def type_check_program(program: Program): stack.append(c) elif op.operand == Intrinsic.MEM: stack.append((DataType.PTR, op.token)) + elif op.operand == Intrinsic.REF: + stack.append((DataType.PTR, op.token)) elif op.operand == Intrinsic.LOAD: assert len(DataType) == 3, "Exhaustive type handling in LOAD intrinsic" if len(stack) < 1: @@ -1122,7 +1127,7 @@ def generate_nasm_linux_x86_64(program: Program, out_file_path: str): assert isinstance(op.operand, int), "This could be a bug in the compilation step" out.write(" jz addr_%d\n" % op.operand) elif op.typ == OpType.INTRINSIC: - assert len(Intrinsic) == 41, "Exhaustive intrinsic handling in generate_nasm_linux_x86_64()" + assert len(Intrinsic) == 42, "Exhaustive intrinsic handling in generate_nasm_linux_x86_64()" if op.operand == Intrinsic.PLUS: out.write(" ;; -- plus --\n") out.write(" pop rax\n") @@ -1268,6 +1273,10 @@ def generate_nasm_linux_x86_64(program: Program, out_file_path: str): elif op.operand == Intrinsic.MEM: out.write(" ;; -- mem --\n") out.write(" push mem\n") + elif op.operand == Intrinsic.REF: + out.write(" ;; -- ref --\n") + out.write(" mov rax, rsp\n") + out.write(" push rax\n") elif op.operand == Intrinsic.LOAD: out.write(" ;; -- load --\n") out.write(" pop rax\n") @@ -1415,7 +1424,7 @@ def generate_nasm_linux_x86_64(program: Program, out_file_path: str): 'include': Keyword.INCLUDE, } -assert len(Intrinsic) == 41, "Exhaustive INTRINSIC_BY_NAMES definition" +assert len(Intrinsic) == 42, "Exhaustive INTRINSIC_BY_NAMES definition" INTRINSIC_BY_NAMES = { '+': Intrinsic.PLUS, '-': Intrinsic.MINUS, @@ -1439,6 +1448,7 @@ def generate_nasm_linux_x86_64(program: Program, out_file_path: str): 'over': Intrinsic.OVER, 'rot': Intrinsic.ROT, 'mem': Intrinsic.MEM, + 'ref': Intrinsic.REF, '.': Intrinsic.STORE, ',': Intrinsic.LOAD, '!': Intrinsic.FORTH_STORE, diff --git a/std/std.porth b/std/std.porth index 3a2c3cbb..a1919f74 100644 --- a/std/std.porth +++ b/std/std.porth @@ -391,6 +391,35 @@ macro puts stdout fputs end +macro putd +// a 32-byte buffer on the stack + +0 swap // a pretty awkward way to bubble up the value +0 swap +0 swap +0 swap + + dup 0 = if + "0" puts + else + ref 8 + 32 + + while over 0 > do + 1 - dup rot + 10 divmod + rot swap '0' + . swap + end + dup + ref 24 + 32 + swap - swap puts + end + drop + +// free the buffer +drop +drop +drop +drop +end + macro eputs stderr fputs end