[Wisp-cvs] wisp/users/dig Makefile.am,1.17,1.18 tran.py,1.98,1.99 interpreter.py,1.8,NONE
Status: Alpha
Brought to you by:
digg
From: <di...@us...> - 2003-05-17 12:59:18
|
Update of /cvsroot/wisp/wisp/users/dig In directory sc8-pr-cvs1:/tmp/cvs-serv14343 Modified Files: Makefile.am tran.py Removed Files: interpreter.py Log Message: folded interpreter.py back into tran.py Index: Makefile.am =================================================================== RCS file: /cvsroot/wisp/wisp/users/dig/Makefile.am,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- Makefile.am 17 May 2003 11:35:28 -0000 1.17 +++ Makefile.am 17 May 2003 12:59:13 -0000 1.18 @@ -8,7 +8,6 @@ EXTRA_DIST = .cvsignore .pycheckrc struburn.wisp bits.py linkie.py \ coff.py elf.py pe.py \ - interpreter.py \ i8086.tran i80386.tran ia16.tran ia32.tran \ winapi.tran \ hello.tran mswhello.tran \ Index: tran.py =================================================================== RCS file: /cvsroot/wisp/wisp/users/dig/tran.py,v retrieving revision 1.98 retrieving revision 1.99 diff -u -d -r1.98 -r1.99 --- tran.py 17 May 2003 12:52:34 -0000 1.98 +++ tran.py 17 May 2003 12:59:14 -0000 1.99 @@ -8,17 +8,307 @@ # #### @(#) $Id$ -from __future__ import generators -from __future__ import nested_scopes +from __future__ import generators, nested_scopes -from getopt import getopt -from interpreter import Lexer, Interpreter, Preprocessor -import elf -import pe +from linkie import Linkie +from shlex import shlex import string -import sys + +def abstract (this, *arg, **narg): + raise 'abstract method was called', (this, arg, narg) + +def simplest_summable (scalar, symbols, registers): + if len(symbols) == len(registers) == 0: + return Integer_Literal(scalar) + elif scalar == len(registers) == 0 and len(symbols) == 1: + return symbols[0] + elif len(registers) == 0: + return Sum((Integer_Literal(scalar),) + tuple(symbols)) + else: + return NotImplemented + +class Summable (object): + def get_scalar (this): return 0 + def get_symbols (this): return () + def get_registers (this): return () + def __add__ (this, that): + scalar = this.get_scalar() + that.get_scalar() + symbols = this.get_symbols() + that.get_symbols() + registers = this.get_registers() + that.get_registers() + return simplest_summable(scalar, symbols, registers) + def __sub__ (this, that): + if len(that.get_symbols()) <> 0 or len(that.get_registers()) <> 0: + return NotImplemented + scalar = this.get_scalar() - that.get_scalar() + symbols = this.get_symbols() + registers = this.get_registers() + return simplest_summable(scalar, symbols, registers) + +class Token (object): pass + +class Stackable (object): + def contained_registers (this): + return () + +class Integer_Literal (long, Stackable, Token, Summable): + def __new__ (cls, i): + return long.__new__(cls, i) + def __add__ (this, that): + return Integer_Literal(long(this) + long(that)) + def __sub__ (this, that): + return Integer_Literal(long(this) - long(that)) + def __repr__ (this): + return 'Integer_Literal(%i)' % long(this) + def get_scalar (this): + return long(this) + +class Symbol_Literal (str, Stackable, Summable): + def __new__ (cls, s): + return str.__new__(cls, s) + def __repr__ (this): + return 'Symbol_Literal(%r)' % str(this) + def get_symbols (this): + return this, + +class Sum (tuple, Summable): + def __new__ (cls, addends): + scalar = 0 + me = [] + for a in addends: + if isinstance(a, Integer_Literal): scalar += long(a) + elif isinstance(a, Symbol_Literal): me.append(a) + else: raise 'improper addend', a + return tuple.__new__(cls, [Integer_Literal(scalar)] + me) + def __repr__ (this): + return 'Sum(%s)' % repr(tuple(this)) + def __str__ (this): + return '+'.join(map(str, this)) + +class Unique (object): + def __init__ (this, name): + this.name = name + def __repr__ (this): + return 'Unique(%r)' % this.name + def __str__ (this): + return this.name +class Unique_Token (Unique, Token): pass + +Semicolon = Unique_Token(';') + +class Token_Source (object): + """After creation, a Token_Source instance will deliver one token +each time its get_token method is called, until the token stream ends. +After that, it will return None.""" + get_token = abstract + +class Lexer (shlex, Token_Source): + def __init__ (this, filename): + shlex.__init__(this, instream = open(filename, 'r'), infile = filename) + this.commenters = '\\' + this.quotes = '"' + this.wordchars += '!#$%*+,-./:;<=>?@[]' + def get_token (this): + tok = shlex.get_token(this) + if tok == '': tok = None + elif tok[:2] == '#o': tok = Integer_Literal(string.atol(tok[2:], 8)) + elif tok[:2] == '#x': tok = Integer_Literal(string.atol(tok[2:], 16)) + elif tok[:2] == '#/' and len(tok) == 3: + tok = Integer_Literal(ord(tok[2])) + else: + try: tok = Integer_Literal(string.atol(tok, 10)) + except: pass + if tok == ';': return Semicolon + else: return tok + def push_file (this, filename): + this.push_source(open(filename, 'r'), filename) + +class Macro_Cursor (Token_Source): + def __init__ (this, sequence): + this.sequence = sequence + this.current = 0 + def get_token (this): + if this.current >= len(this.sequence): return None + datum = this.sequence[this.current] + this.current += 1 + return datum + +class Preprocessor (Token_Source): + __slots__ = ['tss'] + def __init__ (this, toksrc): + object.__init__(this) + this.tss = [toksrc] + def push (this, toksrc): + this.tss.append(toksrc) + def get_token (this): + tok = None + while this.tss and tok == None: + tok = this.tss[-1].get_token() + if tok == None: this.tss.pop() + return tok + +class Register (tuple, Stackable): + def __new__ (cls, items, names = None): + this = tuple.__new__(cls, items) + this.names = names + return this + def parent (this): + if len(this): return Register(this[:-1], this.names) + else: return None + def next (this): + l = list(this) + l[-1] += 1 + return Register(l, this.names) + def child (this, index = 0): + return Register(this + (index,), this.names) + def __repr__ (this): + return 'Register' + tuple.__repr__(this) + def __str__ (this): + if this.names != None and this.names.has_key(this): + return this.names[this] + else: + return '%' + '.'.join(map(str, this)) + def contained_registers (this): + return this, + +class Class_Marker (object, Stackable): + def __init__ (this, id): + this.id = id + +def matchers (object): + if isinstance(object, Class_Marker): + yield object.id + elif isinstance(object, Integer_Literal): + yield 'int' + yield 'lit' + yield 'const' + elif isinstance(object, Symbol_Literal): + yield 'sym' + yield 'lit' + yield 'const' + elif isinstance(object, Sum): + yield 'sum' + yield 'const' + elif isinstance(object, Register): + while object <> None: + yield str(object) # involves appropriate lookup + object = object.parent() + yield 'any' + +MA_PREFIX = 1 + +def make_universal_meaning (fn): + um = { + '...': Unique('...'), + 'tetras': ['dup', '+', 'dup', '+'], # FIXME + } + for m in 'any const int lit sum sym'.split(' '): um[m] = Class_Marker(m) + + # load builtins + bf = open(fn, 'r') + builtins = bf.read() + bf.close() + + for b in builtins.split('\n\n'): + if b[0] != '#': + name, code = b.split('\n', 1) + np = (name + '|').split('|') + name = np[0] + pa = np[1] + exec 'def _p (interpreter, %s):\n%s\n' % (pa, code) + flags = 0 + if pa: flags |= MA_PREFIX + um[name] = 'builtin', _p, flags + return um + +class Interpreter (object): + __slots__ = 'sections current recordee regpaths hanging regstack state meaning register_names toksrc'.split() + universal_meaning = make_universal_meaning('tran-builtins') + + def make_section_switcher (this, name): + def switcher (interpreter): + interpreter.current = interpreter.sections[name] + return switcher + + def __init__ (this, byte_order, sections = ['.text']): + this.sections = {} + this.meaning = Interpreter.universal_meaning.copy() + for s in sections: + this.sections[s] = Linkie(byte_order) + this.meaning[s] = 'builtin', this.make_section_switcher(s), 0 + this.register_names = {} + reg = Register([], names = this.register_names) + this.meaning['reg'] = reg + this.register_names[reg] = 'reg' + this.current = this.sections[sections[0]] + this.recordee = None + this.regpaths = [reg.child()] # for generating new registers + this.hanging = {} + this.regstack = [] + this.state = this.outer_state + this.toksrc = None # only used during interpretation + def match_generator (this, root): + yield root + if len(this.regstack) < 1: yield None # want more registers + m = matchers(this.regstack[-1]) + try: + while 1: + yield root + ' ' + m.next() + except StopIteration: pass + if len(this.regstack) < 2: yield None + m1 = matchers(this.regstack[-2]) + try: + while 1: + n1 = m1.next() + m2 = matchers(this.regstack[-1]) + try: + while 1: yield root + ' ' + n1 + ' ' + m2.next() + except StopIteration: pass + except StopIteration: pass + def outer_state (this, tok): + if isinstance(tok, Integer_Literal): + this.regstack.append(tok) + elif isinstance(tok, str): + root = tok + mg = this.match_generator(root) + try: + while not this.meaning.has_key(tok): + tok = mg.next() + if tok == None: + raise 'stack too empty or meaningless word', root + except StopIteration: + raise 'meaningless word', root + m = this.meaning[tok] + if isinstance(m, list): this.toksrc.push(Macro_Cursor(m)) + elif isinstance(m, Stackable): this.regstack.append(m) + elif isinstance(m, tuple): + mtype = m[0] + if mtype == 'builtin': + if m[2] & MA_PREFIX: + tok = this.toksrc.get_token() + if not isinstance(tok, str): raise 'word expected', tok + m[1](this, tok) + else: + m[1](this) + else: raise 'Unknown meaning type in', `this.meaning[tok]` + else: raise 'Unknown meaning format for', tok + else: raise 'bad token', tok + def run (this, toksrc, verbose = 0): + this.toksrc = Preprocessor(toksrc) + tok = this.toksrc.get_token() + while tok <> None: + if verbose: + print '(%s) %s' % (' '.join(map(str, this.regstack)), tok) + this.state(tok) + tok = this.toksrc.get_token() + this.toksrc = None def main (): + from getopt import getopt + import elf + import pe + import string + import sys + interpreter = Interpreter('<', ['.text', '.data', '.bss']) default_output_names = {'elf': 'a.out', 'pe': 'untitled.exe'} @@ -69,6 +359,6 @@ binary.get_file().tofile(f) f.close() -main() +if __name__ == '__main__': main() # vim: nofen --- interpreter.py DELETED --- |