[Wisp-cvs] wisp/users/dig interpreter.py,NONE,1.1 Makefile.am,1.16,1.17 tran.py,1.94,1.95
Status: Alpha
Brought to you by:
digg
From: <di...@us...> - 2003-05-17 11:35:32
|
Update of /cvsroot/wisp/wisp/users/dig In directory sc8-pr-cvs1:/tmp/cvs-serv7583a Modified Files: Makefile.am tran.py Added Files: interpreter.py Log Message: extracted interpreter.py from tran.py --- NEW FILE: interpreter.py --- #### interpreter.py # # Copyleft © 2003 by Andres Soolo (di...@us...) # This file is licensed under the GNU GPL v2. If you # don't know what that means, please do read the GPL. # #### @(#) $Id: interpreter.py,v 1.1 2003/05/17 11:35:29 digg Exp $ # Not yet importable! 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 (Lexer): __slots__ = ['tss'] def __init__ (this, filename): Lexer.__init__(this, filename) this.tss = [] 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() if tok <> None: return tok else: return Lexer.get_token(this) class Register (tuple, Stackable): def __new__ (cls, *args): return tuple.__new__(cls, args) def parent (this): if len(this): return apply(Register, this[:-1]) else: return None def next (this): l = list(this) l[-1] += 1 return apply(Register, l) def child (this, index = 0): return apply(Register, this + (index,)) def __repr__ (this): return 'Register' + tuple.__repr__(this) def __str__ (this): if Registers.has_key(this): return Registers[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 Registers[object] object = object.parent() yield 'any' def match_generator (root): yield root if len(interpreter.regstack) < 1: yield None # want more registers m = matchers(interpreter.regstack[-1]) try: while 1: yield root + ' ' + m.next() except StopIteration: pass if len(interpreter.regstack) < 2: yield None m1 = matchers(interpreter.regstack[-2]) try: while 1: n1 = m1.next() m2 = matchers(interpreter.regstack[-1]) try: while 1: yield root + ' ' + n1 + ' ' + m2.next() except StopIteration: pass except StopIteration: pass Generic_Register = Register() MA_PREFIX = 1 def make_universal_meaning (fn): um = { 'reg': Generic_Register, '...': 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 (%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'.split() universal_meaning = make_universal_meaning('tran-builtins') def make_section_switcher (this, name): def switcher (): this.current = this.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.current = this.sections[sections[0]] this.recordee = None this.regpaths = [Register(0)] # for generating new registers this.hanging = {} this.regstack = [] this.state = this.outer_state def outer_state (this, tok): if isinstance(tok, Integer_Literal): this.regstack.append(tok) elif isinstance(tok, str): root = tok mg = match_generator(root) try: while not interpreter.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 = interpreter.meaning[tok] if isinstance(m, list): prep.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 = prep.get_token() if not isinstance(tok, str): raise 'word expected', tok m[1](tok) else: m[1]() else: raise 'Unknown meaning type in', `interpreter.meaning[tok]` else: raise 'Unknown meaning format for', tok else: raise 'bad token', tok Index: Makefile.am =================================================================== RCS file: /cvsroot/wisp/wisp/users/dig/Makefile.am,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- Makefile.am 17 May 2003 10:03:50 -0000 1.16 +++ Makefile.am 17 May 2003 11:35:28 -0000 1.17 @@ -8,6 +8,7 @@ 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.94 retrieving revision 1.95 diff -u -d -r1.94 -r1.95 --- tran.py 17 May 2003 11:27:27 -0000 1.94 +++ tran.py 17 May 2003 11:35:29 -0000 1.95 @@ -22,278 +22,7 @@ def abstract (this, *arg, **narg): raise 'abstract method was called', this -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 (Lexer): - __slots__ = ['tss'] - def __init__ (this, filename): - Lexer.__init__(this, filename) - this.tss = [] - 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() - if tok <> None: return tok - else: return Lexer.get_token(this) - -class Register (tuple, Stackable): - def __new__ (cls, *args): - return tuple.__new__(cls, args) - def parent (this): - if len(this): return apply(Register, this[:-1]) - else: return None - def next (this): - l = list(this) - l[-1] += 1 - return apply(Register, l) - def child (this, index = 0): - return apply(Register, this + (index,)) - def __repr__ (this): - return 'Register' + tuple.__repr__(this) - def __str__ (this): - if Registers.has_key(this): - return Registers[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 Registers[object] - object = object.parent() - yield 'any' - -def match_generator (root): - yield root - if len(interpreter.regstack) < 1: yield None # want more registers - m = matchers(interpreter.regstack[-1]) - try: - while 1: - yield root + ' ' + m.next() - except StopIteration: pass - if len(interpreter.regstack) < 2: yield None - m1 = matchers(interpreter.regstack[-2]) - try: - while 1: - n1 = m1.next() - m2 = matchers(interpreter.regstack[-1]) - try: - while 1: yield root + ' ' + n1 + ' ' + m2.next() - except StopIteration: pass - except StopIteration: pass - -Generic_Register = Register() - -MA_PREFIX = 1 - -def make_universal_meaning (fn): - um = { - 'reg': Generic_Register, - '...': 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 (%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'.split() - universal_meaning = make_universal_meaning('tran-builtins') - - def make_section_switcher (this, name): - def switcher (): this.current = this.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.current = this.sections[sections[0]] - this.recordee = None - this.regpaths = [Register(0)] # for generating new registers - this.hanging = {} - this.regstack = [] - this.state = this.outer_state - def outer_state (this, tok): - if isinstance(tok, Integer_Literal): - this.regstack.append(tok) - elif isinstance(tok, str): - root = tok - mg = match_generator(root) - try: - while not interpreter.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 = interpreter.meaning[tok] - if isinstance(m, list): prep.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 = prep.get_token() - if not isinstance(tok, str): raise 'word expected', tok - m[1](tok) - else: - m[1]() - else: raise 'Unknown meaning type in', `interpreter.meaning[tok]` - else: raise 'Unknown meaning format for', tok - else: raise 'bad token', tok +exec open('interpreter.py') interpreter = Interpreter('<', ['.text', '.data', '.bss']) |