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 parse_singleton(self): self.expect('singleton') return { 'u': types.Undefined(), 'undefined': types.Undefined(), 'n': types.Nil(), 'nil': types.Nil(), 't': types.Bool(True), 'true': types.Bool(True), 'f': types.Bool(False), 'false': types.Bool(False) }[self.expect('name').value]
def parse_list(self): self.expect('opening_parentheses') if self.token == 'closing_parentheses': self.advance() return types.Nil() head = self.parse_any() if self.token == 'dot': self.advance() tail = self.parse_any() self.expect('closing_parentheses') return types.Pair(head, tail) result = [head] while self.token != 'closing_parentheses': result.append(self.parse_any()) self.expect('closing_parentheses') return types.Pair.from_sequence(result)
def if_(self, vm, bindings): compiler = mania.compiler.SimpleCompiler(types.Nil()) compiler.compile_any(bindings[Symbol('condition')]) compiler.builder.add(instructions.Eval()) negative_jump = compiler.builder.add(None) compiler.compile_any(bindings[Symbol('positive')]) compiler.builder.add(instructions.Eval()) end_jump = compiler.builder.add(None) compiler.builder.replace( negative_jump, instructions.JumpIfFalse(compiler.builder.index())) if Symbol('negative') in bindings: compiler.compile_any(bindings[Symbol('negative')]) compiler.builder.add(instructions.Eval()) else: compiler.builder.add( instructions.LoadConstant( compiler.builder.constant(types.Undefined()))) end = compiler.builder.add(instructions.Restore()) compiler.builder.replace(end_jump, instructions.Jump(end)) module = compiler.builder.module return [module.code(module.entry_point, len(module))]
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 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 and_(self, vm, bindings): compiler = mania.compiler.SimpleCompiler(types.Nil()) compiler.compile_any(bindings[Symbol('left')]) compiler.builder.add(instructions.Eval()) compiler.builder.add(instructions.Duplicate(1)) left_false = compiler.builder.add(None) compiler.builder.add(instructions.Pop(1)) compiler.compile_any(bindings[Symbol('right')]) compiler.builder.add(instructions.Eval()) end = compiler.builder.add(instructions.Restore()) compiler.builder.replace(left_false, instructions.JumpIfFalse(end)) module = compiler.builder.module return [module.code(module.entry_point, len(module))]
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) ]