Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SizeOf(T) Intrinsic #10

Merged
merged 2 commits into from
Jan 14, 2022
Merged
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
3 changes: 3 additions & 0 deletions lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class Intrinsic(Enum):
CAST = 'cast\([a-zA-Z]\w*\)'
INNER_TUPLE = 'group\.[0-9]+'
CAST_TUPLE = 'group'
SIZE_OF = 'SizeOf\([a-zA-Z]\w*\)'
SYSCALL0 = 'syscall0'
SYSCALL1 = 'syscall1'
SYSCALL2 = 'syscall2'
Expand Down Expand Up @@ -182,6 +183,8 @@ def to_value(s: str, tok: TokenType) -> Any:
elif isinstance(tok, Intrinsic):
if tok == Intrinsic.CAST:
return s[5:-1]
elif tok == Intrinsic.SIZE_OF:
return s[7:-1]
elif tok == Intrinsic.INNER_TUPLE:
return int(s[s.find('.')+1:])
else:
Expand Down
23 changes: 23 additions & 0 deletions prelude/prelude.tlp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
fn !int int ptr -> ptr do
dup push !64 pop cast(int) SizeOf(int) + cast(ptr)
end

fn @int ptr -> int ptr do
cast(int) SizeOf(int) - cast(ptr) dup @64 cast(int) swap
end

fn !bool int ptr -> ptr do
dup push !64 pop cast(int) SizeOf(bool) + cast(ptr)
end

fn @bool ptr -> bool ptr do
cast(int) SizeOf(bool) - cast(ptr) dup @64 cast(bool) swap
end

fn !ptr ptr ptr -> ptr do
dup push !64 pop cast(int) SizeOf(ptr) + cast(ptr)
end

fn @ptr ptr -> ptr ptr do
cast(int) SizeOf(ptr) - cast(ptr) dup @64 cast(ptr) swap
end
5 changes: 0 additions & 5 deletions std.tlp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@ fn NULL -> ptr do
0 cast(ptr)
end

const SizeOf(int) 8 end
const SizeOf(bool) 8 end
const SizeOf(ptr) 8 end
const SizeOf(Str) SizeOf(int) SizeOf(ptr) + end

const PUTD_BUFFER_SIZE 20 end
reserve putd_buffer PUTD_BUFFER_SIZE end

Expand Down
1 change: 1 addition & 0 deletions tests/compiler_errors/const_size_of_unknown_type.tlp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const foo SizeOf(bar) end
7 changes: 7 additions & 0 deletions tests/compiler_errors/const_size_of_unknown_type.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
args: ['python3', 'tulip.py', './tests/compiler_errors/const_size_of_unknown_type.tlp']
-------- stdout ----------
--------------------------
-------- stderr ----------
./tests/compiler_errors/const_size_of_unknown_type.tlp:1:11 [ERROR]: Cannot get size of unknown type `bar`.
--------------------------
exit code: 1
1 change: 1 addition & 0 deletions tests/compiler_errors/size_of_none.tlp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SizeOf() puts
7 changes: 7 additions & 0 deletions tests/compiler_errors/size_of_none.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
args: ['python3', 'tulip.py', './tests/compiler_errors/size_of_none.tlp']
-------- stdout ----------
--------------------------
-------- stderr ----------
./tests/compiler_errors/size_of_none.tlp:1:1 [ERROR]: Unrecognized WORD SizeOf().
--------------------------
exit code: 1
1 change: 1 addition & 0 deletions tests/compiler_errors/size_of_unknown_type.tlp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SizeOf(foo) putu
7 changes: 7 additions & 0 deletions tests/compiler_errors/size_of_unknown_type.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
args: ['python3', 'tulip.py', './tests/compiler_errors/size_of_unknown_type.tlp']
-------- stdout ----------
--------------------------
-------- stderr ----------
./tests/compiler_errors/size_of_unknown_type.tlp:1:1 [ERROR]: Cannot get size of unknown type `foo`.
--------------------------
exit code: 1
13 changes: 13 additions & 0 deletions tests/functional_tests/size_of.tlp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
SizeOf(int) putu
SizeOf(bool) putu
SizeOf(ptr) putu
SizeOf(Str) putu

struct foo
int
bool
ptr
Str
end

SizeOf(foo) putu
18 changes: 18 additions & 0 deletions tests/functional_tests/size_of.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
args: ['python3', 'tulip.py', './tests/functional_tests/size_of.tlp']
-------- stdout ----------
--------------------------
-------- stderr ----------
--------------------------
exit code: 0
##########################
args: ['./output']
-------- stdout ----------
8
8
8
16
40
--------------------------
-------- stderr ----------
--------------------------
exit code: 0
57 changes: 49 additions & 8 deletions tulip.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class Function:
Intrinsic.SPLIT: Signature(pops=[T], puts=lambda List_T: StructMembers[List_T[0]] if List_T[0].Struct else None),
Intrinsic.RPUSH: Signature(pops=[T], puts=[], rputs=[T]),
Intrinsic.RPOP: Signature(pops=[], puts=[T], rpops=[T]),
Intrinsic.SIZE_OF: Signature(pops=[], puts=[INT]),
# Intrinsic.CAST creates signatures dynamically based on the struct
# Intrinsic.INNER_TUPLE creates a signature dynamically based on the tuple on the top of the stack.
# Intrinsic.CAST_TUPLE creates signatures dynamically based on the number of elements asked to group
Expand All @@ -141,6 +142,8 @@ class Function:
assert len(signatures) == len(OpType) - N_SUM_IGNORE + len(Intrinsic), \
f"Not all OpTypes and Intrinsics have a signature. Expected {len(OpType) - N_SUM_IGNORE + len(Intrinsic)} Found {len(signatures)}"

PRELUDE_SIZE = 0


def compiler_error(predicate: bool, token: Token, msg):
if not predicate:
Expand Down Expand Up @@ -269,8 +272,9 @@ def parse_tokens_until_keywords(
)

if tok.typ == Intrinsic.CAST_TUPLE:
global PRELUDE_SIZE
compiler_error(
len(program) > 0,
len(program) > PRELUDE_SIZE,
tok,
f"`GROUP` expects a preceding `UINT`, but found end of file instead"
)
Expand Down Expand Up @@ -394,6 +398,14 @@ def eval_const_ops(program: Program, tok: Token) -> Optional[Op]:
assert isinstance(a, int)
assert isinstance(b, int)
stack.append(a << b)
elif op.operand == Intrinsic.SIZE_OF:
compiler_error(
op.tok.value in TypeDict.keys(),
op.tok,
f"Cannot get size of unknown type `{op.tok.value}`."
)

stack.append(TypeDict[op.tok.value].Size * 8)
else:
compiler_error(
False,
Expand Down Expand Up @@ -1214,11 +1226,23 @@ def parse_while_block_from_tokens(
program[do_tok_loc].operand = len(program)


def program_from_tokens(tokens: List[Token]) -> Tuple[Program, FunctionMeta, MemoryMap]:
program: Program = []
fn_meta: FunctionMeta = {}
def program_from_prelude() -> Tuple[Program, FunctionMeta, MemoryMap]:
prelude_tokens = tokenize("prelude/prelude.tlp")
program, fn_meta, reserved_mem = program_from_tokens(prelude_tokens)
global PRELUDE_SIZE
PRELUDE_SIZE = len(program)
return (program, fn_meta, reserved_mem)


def program_from_tokens(
tokens: List[Token],
program: Program = [],
fn_meta: FunctionMeta = {},
reserved_memory: MemoryMap = {},
) -> Tuple[Program, FunctionMeta, MemoryMap]:


const_values: ConstMap = {}
reserved_memory: MemoryMap = {}
tokens.reverse()

expected_keywords: List[Keyword] = [
Expand Down Expand Up @@ -1726,6 +1750,11 @@ def type_check_program(
pops=[INT],
puts=[PTR]
)
elif t.Ident == BOOL.Ident:
sig = Signature(
pops=[INT],
puts=[BOOL]
)
else:
compiler_error(
False,
Expand Down Expand Up @@ -2085,7 +2114,16 @@ def compile_program(out_path: str, program: Program, fn_meta: FunctionMeta, rese
out, f"{ip}_{i}", members[-2].Size, members[-1].Size)
op_drop_to_asm(out, members[-2].Size)
del members[-2]

elif op.operand == Intrinsic.SIZE_OF:
compiler_error(
op.tok.value in TypeDict.keys(),
op.tok,
f"Cannot get size of unknown type `{op.tok.value}`."
)
out.write(
f";; --- {op.op} {op.operand} {op.tok.value} --- \n")
out.write(
f" push {TypeDict[op.tok.value].Size * 8}\n")
elif op.operand == Intrinsic.SYSCALL0:
out.write(f";; --- {op.op} {op.operand} --- \n")
out.write(f" pop rax\n") # SYSCALL NUM
Expand Down Expand Up @@ -2206,8 +2244,11 @@ def usage(msg: str):
# for i, tok in enumerate(tokens):
# print(f"{i} -- {tok.typ}: {tok.value}")
# print("-------------------------------------------")

program, fn_meta, reserved_memory = program_from_tokens(tokens)
program, fn_meta, reserved_memory = program_from_prelude()
program, fn_meta, reserved_memory = program_from_tokens(
tokens,
program, fn_meta, reserved_memory
)
# print("-------------------------------------------")
# for ip, op in enumerate(program):
# print(f"{ip} -- {op.op}: {op.operand} TokenType: {op.tok.typ}")
Expand Down