Skip to content

Commit

Permalink
Pretty return (#12)
Browse files Browse the repository at this point in the history
* Add basic support for iterators and lists

* Added pretty functions and get_type_name function

* Added printing of elements of lists
  • Loading branch information
ViliamVadocz authored Apr 6, 2020
1 parent 0c29d76 commit 3c19651
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 35 deletions.
30 changes: 12 additions & 18 deletions examples/test.vlp
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
# a jungle of random tests
f = (x, [y, z]) => [&x..10, y..z]
a = f(0, [0, 10])
[b, c] = a

# functions
# :> f

# testing compound assignment operators
a = 3
a += 2
a /= 5
# tuples
# :> [1 > 0, [1, 0.0], f, b, c]

b = 2.5
b *= 4.0
b -= a.5 # conversion
# iterators
# :> c :: i => [i, i.0, f, f(i-5, [0, 2])]

f = () => ~b # conversion

c = [1.0, 2, [3.0, 4]] # tuples

[d, _, e] = c # tuple decomposition

g = (-2)..2 # ranges

# printing various types, float precision
:> [b, 1 > 0, !(5 == ~5.0), [1.0, 2, [3.0, 4]], 1.0 / 3.0, f(), f, [f], g[1]]
# lists
:> b
2 changes: 2 additions & 0 deletions volpe/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ def number_iter(self, tree: TypeTree):
start = read_environment(b, args[0], env_types)[0]
b.ret(b.add(start, args[1]))

# TODO going in reverse

env_ptr = write_environment(self.builder, [values[0]])
list_value = tree.return_type(ir.Undefined)
list_value = self.builder.insert_value(list_value, self.builder.insert_value(closure, env_ptr, 3), 0)
Expand Down
100 changes: 86 additions & 14 deletions volpe/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,16 @@


# All these initializations are required for code generation!
from volpe_types import int1, int32, flt32, flt64, VolpeTuple, VolpeClosure
from volpe_types import (
int1,
int32,
flt32,
flt64,
VolpeTuple,
VolpeClosure,
VolpeIterator,
VolpeList
)

llvm.initialize()
llvm.initialize_native_target()
Expand Down Expand Up @@ -38,28 +47,91 @@ def compile_and_run(llvm_ir, result_type):


def determine_c_type(volpe_type, depth=0):
# Interpret result type.
"""Interpret the volpe type and return a corresponding C type."""
# Simple types:
if volpe_type == int1:
return c_bool
if volpe_type == int32:
return c_int32
if volpe_type == flt32:
return c_float
if volpe_type == flt64:
return c_double

# Aggregate types:
if isinstance(volpe_type, VolpeTuple):
elems = volpe_type.elements
class CTuple(Structure):
_fields_ = [(f"elem{i}", determine_c_type(elem, depth+1)) for i, elem in enumerate(elems)]
def __repr__(self):
return "[" + ", ".join([str(getattr(self, tup[0])) for tup in self._fields_]) + "]"

return POINTER(CTuple) if depth == 0 else CTuple

if isinstance(volpe_type, VolpeList):
element_type = determine_c_type(volpe_type.element_type, depth+1)
class CList(Structure):
_fields_ = [("elems", POINTER(element_type)), ("length", c_int32)]
def __repr__(self):
if depth == 0:
elems = getattr(self, "elems")
length = getattr(self, "length")
return "&<" + ", ".join([str(elem) for elem in elems[:length]]) + ">"
return get_type_name(volpe_type)
return POINTER(CList) if depth == 0 else CList

if isinstance(volpe_type, VolpeClosure):
elems = volpe_type.elements
class CFunc(Structure):
_fields_ = [("func", POINTER(None)), ("c_func", POINTER(None)), ("f_func", POINTER(None)), ("env", POINTER(None))]
def __repr__(self):
return "*function*"
if depth == 0:
func = elems[0].pointee
input_type = ", ".join([get_type_name(i) for i in func.args[1:]])
return_type = get_type_name(func.return_type)
return f"function ({input_type}) => {return_type}"
return get_type_name(volpe_type)
return CFunc
elif volpe_type == int1:
return c_bool
elif volpe_type == int32:
return c_int32
elif volpe_type == flt32:
return c_float
elif volpe_type == flt64:
return c_double
else:
return None

if isinstance(volpe_type, VolpeIterator):
class CFunc(Structure):
_fields_ = [("func", POINTER(None)), ("c_func", POINTER(None)), ("f_func", POINTER(None)), ("env", POINTER(None))]
class CIterator(Structure):
_fields_ = [("func", CFunc), ("length", c_int32)]
def __repr__(self):
if depth == 0:
# TODO maybe include length?
func = volpe_type.elements[0].elements[0].pointee
return_type = get_type_name(func.return_type)
return f"iterator of {return_type}"
return get_type_name(volpe_type)
return CIterator

# Unknown type
return None


def get_type_name(volpe_type):
"""Get short Volpe names for types."""
# Simple types:
if volpe_type == int1:
return "bool"
if volpe_type == int32:
return "int32"
if volpe_type == flt32:
return "flt32"
if volpe_type == flt64:
return "flt64"

# Aggregate types:
if isinstance(volpe_type, VolpeTuple):
type_reprs = ", ".join([get_type_name(elem) for elem in volpe_type.elements])
return f"[{type_reprs}]"
if isinstance(volpe_type, VolpeList):
return "*list*"
if isinstance(volpe_type, VolpeClosure):
return "*function*"
if isinstance(volpe_type, VolpeIterator):
return "*iterator*"

# Unknown type
return None
7 changes: 4 additions & 3 deletions volpe/run_volpe.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from builder_utils import build_func
from compile import compile_and_run
from tree import TypeTree
from volpe_types import pint8, int32, VolpeTuple, target_data, VolpeClosure, copy_func, free_func
from volpe_types import pint8, int32, VolpeTuple, VolpeList, target_data, VolpeClosure, copy_func, free_func


def volpe_llvm(tree: TypeTree, verbose=False, fast=False):
Expand Down Expand Up @@ -55,17 +55,18 @@ def scope(name):
b.ret_void()

return_type = func_type.func.return_type
if isinstance(return_type, VolpeTuple):
if isinstance(return_type, (VolpeTuple, VolpeList)):
return_type = return_type.as_pointer()

main_func = ir.Function(module, ir.FunctionType(return_type, []), "main")
with build_func(main_func) as (b, _):
b: ir.IRBuilder
res = b.call(func, [pint8(ir.Undefined)])
if isinstance(res.type, VolpeTuple):
if isinstance(res.type, (VolpeTuple, VolpeList)):
ptr = b.bitcast(b.call(module.malloc, [int32(res.type.get_abi_size(target_data))]), return_type)
b.store(res, ptr)
res = ptr
# TODO return list and vector as pointer
b.ret(res)

if verbose:
Expand Down

0 comments on commit 3c19651

Please sign in to comment.