Skip to content
This repository was archived by the owner on Nov 11, 2021. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
18 changes: 14 additions & 4 deletions porth.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class Intrinsic(Enum):
OVER=auto()
ROT=auto()
MEM=auto()
REF=auto()
LOAD=auto()
STORE=auto()
FORTH_LOAD=auto()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down
29 changes: 29 additions & 0 deletions std/std.porth
Original file line number Diff line number Diff line change
Expand Up @@ -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