Skip to content

Commit 4c46a43

Browse files
committed
test programs (yet to be compiled/executed); syntax tree structure and a naive transpiler to python code
1 parent 327a2c3 commit 4c46a43

24 files changed

+475
-0
lines changed

LICENSE.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2+
Version 2, December 2004
3+
4+
Copyright (C) 2004 Sam Hocevar <[email protected]>
5+
6+
Everyone is permitted to copy and distribute verbatim or modified
7+
copies of this license document, and changing it is allowed as long
8+
as the name is changed.
9+
10+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11+
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12+
13+
0. You just DO WHAT THE FUCK YOU WANT TO.
14+

Makefile

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
SHELL := bash
2+
.ONESHELL:
3+
.SHELLFLAGS := -eu -o pipefail -c
4+
.DELETE_ON_ERROR:
5+
MAKEFLAGS += --warn-undefined-variables
6+
MAKEFLAGS += --no-builtin-rules
7+
8+
VENV := $(shell echo $${VIRTUAL_ENV-.venv})
9+
PY3 := $(shell command -v python3 2 /dev/null)
10+
PYTHON := $(VENV)/bin/python
11+
INSTALL_STAMP := $(VENV)/.install.stamp
12+
13+
.PHONY: test run clean
14+
15+
$(PYTHON):
16+
@if [ -z $(PY3) ]; then echo "Python 3 could not be found."; exit 2; fi
17+
echo $(PY3) -m venv $(VENV)
18+
$(PY3) -m venv $(VENV)
19+
20+
$(INSTALL_STAMP): $(PYTHON) requirements.txt
21+
$(PYTHON) -m pip install -r requirements.txt
22+
touch $(INSTALL_STAMP)
23+
24+
test: $(INSTALL_STAMP)
25+
$(PYTHON) -m pytest --cov . -v --cov-report term-missing ./tests/
26+
27+
run: $(INSTALL_STAMP)
28+
@$(PYTHON) compiler.py
29+
30+
clean:
31+
rm -rf $(VENV) .pytest_cache .coverage
32+
find . -type f -name *.pyc -delete
33+
find . -type d -name __pycache__ -delete
34+

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,9 @@ fun main() {
4747
There will no be dynamic memory allocation, no pointers, no garbage collection. There will be nested functions, function overloading and type checking.
4848

4949
And as usual, there will be a program with a raytracer :)
50+
51+
## run tests
52+
```sh
53+
make test
54+
```
55+

requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
sly
2+
pytest
3+
pytest-cov

syntree.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
class Type:
2+
VOID = 0
3+
INT = 1
4+
BOOL = 2
5+
STRING = 3
6+
7+
class Function:
8+
def __init__(self, name, args, var, fun, body, deco=None):
9+
self.name = name # function name, string
10+
self.args = args # function arguments, list of tuples (name, type)
11+
self.var = var # local variables, list of tuples (name, type)
12+
self.fun = fun # nested functions, list of Function nodes
13+
self.body = body # function body, list of statement nodes (Print/Return/Assign/While/IfThenElse/FunCall)
14+
self.deco = deco or {} # decoration dictionary to be filled by the parser (line number) and by the semantic analyzer (return type, scope id etc)
15+
16+
# statements
17+
class Print:
18+
def __init__(self, expr, newline, deco=None):
19+
self.expr, self.newline, self.deco = expr, newline, deco or {}
20+
21+
class Return:
22+
def __init__(self, expr, deco=None):
23+
self.expr, self.deco = expr, deco or {}
24+
25+
class Assign:
26+
def __init__(self, name, expr, deco=None):
27+
self.name, self.expr, self.deco = name, expr, deco or {}
28+
29+
class While:
30+
def __init__(self, expr, body, deco=None):
31+
self.expr, self.body, self.deco = expr, body, deco or {}
32+
33+
class IfThenElse:
34+
def __init__(self, expr, ibody, ebody, deco=None):
35+
self.expr, self.ibody, self.ebody, self.deco = expr, ibody, ebody, deco or {}
36+
37+
# expressions
38+
class ArithOp:
39+
def __init__(self, op, left, right, deco=None):
40+
self.op, self.left, self.right, self.deco = op, left, right, deco or {}
41+
42+
class LogicOp:
43+
def __init__(self, op, left, right, deco=None):
44+
self.op, self.left, self.right, self.deco = op, left, right, deco or {}
45+
46+
class Integer:
47+
def __init__(self, value, deco=None):
48+
self.value, self.deco = value, deco or {}
49+
50+
class Boolean:
51+
def __init__(self, value, deco=None):
52+
self.value, self.deco = value, deco or {}
53+
54+
class String:
55+
def __init__(self, value, deco=None):
56+
self.value, self.deco = value, deco or {}
57+
58+
class Var:
59+
def __init__(self, name, deco=None):
60+
self.name, self.deco = name, deco or {}
61+
62+
class FunCall: # depending on the context, a function call can be a statement or an expression
63+
def __init__(self, name, args, deco=None):
64+
self.name, self.args, self.deco = name, args, deco or {}

test-data/fixed-point.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-3.14158

test-data/fixed-point.wend

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
fun main() {
2+
3+
// This program outputs a decimal representation of a signed 32-bit fixed point number.
4+
// It prints the number one character at a time without ever printing an integer type expression,
5+
// like we would make it with aid of _write system call.
6+
7+
fun print_fixed_point(x:int, shift:int) {
8+
var decpr:int;
9+
var i:int;
10+
11+
fun decpr(shift:int) : int { // number of meaningful digits after the decimal point
12+
var decpr:int;
13+
decpr = 0;
14+
while shift>0 {
15+
decpr = decpr + 1;
16+
shift = shift / 10;
17+
}
18+
return decpr;
19+
}
20+
21+
fun print_digit(d:int) {
22+
if d==0 {
23+
print "0";
24+
} else {
25+
if d==1 {
26+
print "1";
27+
} else {
28+
if d==2 {
29+
print "2";
30+
} else {
31+
if d==3 {
32+
print "3";
33+
} else {
34+
if d==4 {
35+
print "4";
36+
} else {
37+
if d==5 {
38+
print "5";
39+
} else {
40+
if d==6 {
41+
print "6";
42+
} else {
43+
if d==7 {
44+
print "7";
45+
} else {
46+
if d==8 {
47+
print "8";
48+
} else {
49+
if d==9 {
50+
print "9";
51+
} else {
52+
print "invalid input";
53+
}}}}}}}}}}
54+
}
55+
56+
fun print_integer(x:int) {
57+
if x>0 {
58+
print_integer(x / 10);
59+
print_digit(x % 10); // recursion to reverse the print
60+
}
61+
}
62+
63+
if x<0 {
64+
print "-";
65+
x = -x;
66+
}
67+
68+
print_integer(x / shift);
69+
print ".";
70+
71+
decpr = decpr(shift);
72+
i = 0;
73+
x = (x % shift) * 10;
74+
while i<decpr {
75+
print_digit((x / shift) % 10);
76+
x = (x % shift) * 10;
77+
i = i + 1;
78+
}
79+
println "";
80+
}
81+
82+
// print number -pi up to 16 bits (10^-5) precision
83+
// 205887 = int(pi * 2^16)
84+
print_fixed_point(-205887, 65536);
85+
}
86+

test-data/helloworld.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hello world

test-data/helloworld.wend

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fun main() {
2+
println "hello world";
3+
}
4+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
odd(-255) = True

0 commit comments

Comments
 (0)