[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'])
|