def let(self, vm, bindings): variables = list(bindings[Symbol('variables')] or []) values = list(bindings[Symbol('values')] or []) if len(values) != len(variables): raise SyntaxError('let bindings need a value') compiler = mania.compiler.SimpleCompiler(types.Nil()) for name in variables: if ':' in name.value and any(c != ':' for c in name.value): raise types.ExpandError() compiler.builder.add( instructions.Store(compiler.builder.constant(name))) for node in bindings[Symbol('body')]: compiler.compile_any(node) compiler.builder.add(instructions.Eval()) compiler.builder.add(instructions.Return()) size = compiler.builder.index() compiler.builder.add(instructions.LoadCode(0, size)) compiler.builder.add(instructions.BuildFunction()) if Symbol('name') in bindings: name = bindings[Symbol('name')] if ':' in name.value and any(c != ':' for c in name.value): raise types.ExpandError() compiler.builder.add( instructions.Store(compiler.builder.constant(name))) compiler.builder.add( instructions.Load(compiler.builder.constant(name))) for value in values: compiler.compile_any(value) compiler.builder.add(instructions.Eval()) compiler.builder.add(instructions.Call(len(values))) compiler.builder.add(instructions.Return()) entry_point = compiler.builder.index() compiler.builder.add(instructions.LoadCode(size, entry_point - size)) compiler.builder.add(instructions.BuildFunction()) compiler.builder.add(instructions.Call(0)) module = compiler.builder.module module.entry_point = entry_point return [ module.code(module.entry_point, len(module) - module.entry_point) ]
def define_syntax(self, vm, bindings): rules = zip(bindings[Symbol('pattern')], bindings[Symbol('template')]) compiler = mania.compiler.SimpleCompiler(types.Nil()) for pattern, templates in rules: compiler.compile_any(pattern) compiler.builder.add(instructions.BuildPattern()) for template in templates: compiler.compile_any(template) compiler.builder.add(instructions.BuildTemplate(len(templates))) compiler.builder.add(instructions.BuildRule()) compiler.builder.add(instructions.BuildMacro(len(rules))) compiler.builder.add(instructions.Duplicate(1)) compiler.builder.add( instructions.Store( compiler.builder.constant(bindings[Symbol('name')]))) module = compiler.builder.module return [ module.code(module.entry_point, len(module) - module.entry_point) ]
def compile_function(self, bindings): parameters = bindings[Symbol('parameters')] or [] body = bindings[Symbol('body')] or [] compiler = mania.compiler.SimpleCompiler(types.Nil()) empty_check = None for i, parameter in enumerate(parameters): if ':' in parameter.value and any(c != ':' for c in parameter.value): raise types.ExpandError() if i + 1 < len(parameters) and isinstance(parameters[i + 1], Ellipsis): if i + 2 < len(parameters): raise mania.types.ExpandError() empty_check = compiler.builder.add(None) compiler.compile_any(types.Nil()) loop = compiler.builder.add(instructions.BuildPair()) end = compiler.builder.add(None) compiler.builder.add(instructions.Jump(loop)) index = compiler.builder.index() compiler.compile_any(types.Nil()) store = compiler.builder.add(instructions.Reverse()) compiler.builder.add( instructions.Store(compiler.builder.constant(parameter))) if empty_check is not None: compiler.builder.replace(end, instructions.JumpIfSize(1, store)) compiler.builder.replace(empty_check, instructions.JumpIfEmpty(index)) break for node in body: compiler.compile_any(node) compiler.builder.add(instructions.Eval()) compiler.builder.add(instructions.Return()) compiler.builder.entry_point = compiler.builder.index() compiler.builder.add( instructions.LoadCode(0, compiler.builder.entry_point)) compiler.builder.add(instructions.BuildFunction()) return compiler
def define_function(self, vm, bindings): name = bindings[Symbol('name')] if ':' in name.value and any(c != ':' for c in name.value): raise mania.types.ExpandError() compiler = self.compile_function(bindings) compiler.builder.add(instructions.Duplicate(1)) compiler.builder.add( instructions.Store(compiler.builder.constant(name))) module = compiler.builder.module return [ module.code(module.entry_point, len(module) - module.entry_point) ]
def define_value(vm, bindings): name = bindings[Symbol('name')] if ':' in name.value and any(c != ':' for c in name.value): raise types.ExpandError() compiler = mania.compiler.SimpleCompiler(types.Nil()) compiler.compile_any(bindings[Symbol('value')]) compiler.builder.add(instructions.Eval()) compiler.builder.add(instructions.Duplicate(1)) compiler.builder.add( instructions.Store(compiler.builder.constant(name))) module = compiler.builder.module return [ module.code(module.entry_point, len(module) - module.entry_point) ]
def import_(self, vm, bindings): compiler = mania.compiler.SimpleCompiler(types.Nil()) compiler.compile_any(bindings[Symbol('name')]) compiler.builder.add(instructions.Eval()) compiler.builder.add(instructions.LoadModule()) if Symbol('imports') in bindings: for name in bindings[Symbol('imports')]: compiler.builder.add( instructions.LoadField(compiler.builder.constant(name))) compiler.builder.add( instructions.Store(compiler.builder.constant(name))) module = compiler.builder.module return [ module.code(module.entry_point, len(module) - module.entry_point) ]
def define_values(self, vm, bindings): compiler = mania.compiler.SimpleCompiler(types.Nil()) compiler.compile_any(bindings[Symbol('body')]) compiler.builder.add(instructions.Eval()) for name in bindings[Symbol('names')]: compiler.builder.add(instructions.Duplicate(1)) compiler.builder.add(instructions.Head()) compiler.builder.add( instructions.Store(compiler.builder.constant(name))) compiler.builder.add(instructions.Tail()) compiler.builder.add(instructions.Pop(1)) module = compiler.builder.module return [ module.code(module.entry_point, len(module) - module.entry_point) ]