parent
cf4a1ca9de
commit
f88a2e18cb
125
mode/tal.py
125
mode/tal.py
|
@ -1,5 +1,7 @@
|
|||
from method import Argument, Method
|
||||
from mode import Fundamental
|
||||
from lex import Grammar, PatternRule, RegionRule
|
||||
import re
|
||||
|
||||
class TalGrammar(Grammar):
|
||||
rules = [
|
||||
|
@ -7,20 +9,20 @@ class TalGrammar(Grammar):
|
|||
RegionRule('comment', r'\(', Grammar, '\)'),
|
||||
PatternRule('delimiter', r'[\[\]{}]'),
|
||||
PatternRule('tal.inst', r'(BRK|LIT|INC|POP|DUP|NIP|SWP|OVR|ROT|EQU|NEQ|GTH|LTH|JMP|JCN|JSR|STH|LDZ|STZ|LDR|STR|LDA|STA|DEI|DEO|ADD|SUB|MUL|DIV|AND|ORA|EOR|SFT)2?k?r?'), # instructions
|
||||
PatternRule('tal.defmacro', r'%[^ ]+'), # macro-define
|
||||
PatternRule('tal.pad', r'\|[^ ]+'), # pad (absolute)
|
||||
PatternRule('tal.pad', r'\$[^ ]+'), # pad (relative)
|
||||
PatternRule('tal.deflabel', r'@[^ ]+'), # label-define
|
||||
PatternRule('tal.defsublabel', r'&[^ ]+'), # sublabel-define
|
||||
PatternRule('tal.spacer', r'/[^ ]+'), # sublabel-spacer
|
||||
PatternRule('tal.hex', r'#[0-9a-fA-F]+'), # literal hex
|
||||
PatternRule('tal.addr', r'\.[^/ ]+'), # little addr (zero page)
|
||||
PatternRule('tal.addr', r',[^/ ]+'), # little addr (relative)
|
||||
PatternRule('tal.addr', r';[^/ ]+'), # little addr (absolute)
|
||||
PatternRule('tal.addr', r':[^/ ]+'), # raw addr
|
||||
PatternRule('tal.addr', r'\'[^/ ]+'), # raw char
|
||||
PatternRule('tal.addr', r'\"[^/ ]+'), # raw word
|
||||
PatternRule('tal.word', r'[^ ]+'),
|
||||
PatternRule('tal.defmacro', r'%[^ \t\n]+'), # macro-define
|
||||
PatternRule('tal.pad', r'\|[^ \t\n]+'), # pad (absolute)
|
||||
PatternRule('tal.pad', r'\$[^ \t\n]+'), # pad (relative)
|
||||
PatternRule('tal.deflabel', r'@[^ \t\n]+'), # label-define
|
||||
PatternRule('tal.defsublabel', r'&[^ \t\n]+'), # sublabel-define
|
||||
PatternRule('tal.spacer', r'/[^ \t\n]+'), # sublabel-spacer
|
||||
PatternRule('tal.number', r'#[0-9a-fA-F]+'), # literal number
|
||||
PatternRule('tal.addr', r'\.[^/ \t\n]+'), # little addr (zero page)
|
||||
PatternRule('tal.addr', r',[^/ \t\n]+'), # little addr (relative)
|
||||
PatternRule('tal.addr', r';[^/ \t\n]+'), # little addr (absolute)
|
||||
PatternRule('tal.addr', r':[^/ \t\n]+'), # raw addr
|
||||
PatternRule('tal.addr', r'\'[^/ \t\n]+'), # raw char
|
||||
PatternRule('tal.addr', r'\"[^/ \t\n]+'), # raw word
|
||||
PatternRule('tal.word', r'[^ \t\n]+'),
|
||||
PatternRule('eol', '\n'),
|
||||
]
|
||||
|
||||
|
@ -55,10 +57,102 @@ hi_cyan = ('cyan155', 'default')
|
|||
lo_blue = ('blue113', 'default')
|
||||
hi_blue = ('blue225', 'default')
|
||||
|
||||
class Taldoc(Method):
|
||||
'''View documentation'''
|
||||
ops = {
|
||||
# instructions
|
||||
'BRK': ['Break', [[], []], None, 'halt the program'],
|
||||
'LIT': ['Literal', [[], ['a']], None, 'push the next value onto the stack'],
|
||||
'INC': ['Increment', [['a'] , ['b']], None, 'adds one to the top of the stack'],
|
||||
'POP': ['Pop', [['a'], []], None, 'remove the top of the stack'],
|
||||
'DUP': ['Duplicate', [['a'], ['a', 'a']], None, 'duplicate the top of the stack'],
|
||||
'NIP': ['Nip', [['a', 'b'], ['b']], None, 'remove the second value (a)'],
|
||||
'SWP': ['Swap', [['a', 'b'], ['b', 'a']], None, 'swap the top two stack values'],
|
||||
'OVR': ['Over', [['a', 'b'], ['a', 'b', 'a']], None, 'duplicate the second value (a) to the top of the stack'],
|
||||
'ROT': ['Rotate', [['a', 'b', 'c'], ['b', 'c', 'a']], None, 'left rotate the top three values'],
|
||||
# logic
|
||||
'EQU': ['Equal', [['a', 'b'], ['bool']], None, 'push 01 if a == b; push 00 otherwise'],
|
||||
'NEQ': ['Not Equal', [['a', 'b'], ['bool']], None, 'push 01 if a != b; push 00 otherwise'],
|
||||
'GTH': ['Greater Than', [['a', 'b'], ['bool^']], None, 'push 01 if a > b; push 00 otherwise'],
|
||||
'LTH': ['Less Than', [['a', 'b'], ['bool^']], None, 'push 01 if a < b; push 00 otherwise'],
|
||||
# control flow
|
||||
'JMP': ['Jump', [['x'], []], None, 'modify the program counter using addr'],
|
||||
'JCN': ['Jump Conditional', [['bool^ addr'], []], None, 'if bool != 00, modify the program counter using addr'],
|
||||
'JSR': ['Jump Stash Return', [['addr'], []], [[], ['pc']], 'push program counter onto return stack, then modify the program counter using addr'],
|
||||
'STH': ['Stash', [['a'], []], [[], ['a']], 'pop the top of the stack and push it onto the return stack'],
|
||||
# memory
|
||||
'LDZ': ['Load Zero-Page', [['addr^'], ['val']], None, 'read value from first 256 bytes of memory onto the stack'],
|
||||
'STZ': ['Store Zero-Page', [['val', 'addr^'], []], None, 'write top of stack into the first 256 bytes of memory'],
|
||||
'LDR': ['Load Relative', [['addr^'], ['val']], None, ''],
|
||||
'STR': ['Store Relative', [['val', 'addr^'], []], None, ''],
|
||||
'LDA': ['Load Absolute', [['addr*'], ['val']], None, ''],
|
||||
'STA': ['Store Absolute', [['val', 'addr*'], []], None, ''],
|
||||
'DEI': ['Device In', [['addr^'], ['val']], None, ''],
|
||||
'DEO': ['Device Out', [['val', 'addr^'], []], None, ''],
|
||||
# arithmetic
|
||||
'ADD': ['Add', [['a', 'b'], ['a+b']], None, ''],
|
||||
'SUB': ['Subtract', [['a', 'b'], ['a-b']], None, ''],
|
||||
'MUL': ['Multiply', [['a', 'b'], ['a*b']], None, ''],
|
||||
'DIV': ['Divide', [['a', 'b'], ['a/b']], None, ''],
|
||||
# bitwise
|
||||
'AND': ['And', [['a', 'b'], ['a&b']], None, ''],
|
||||
'ORA': ['Or', [['a', 'b'], ['a|b']], None, ''],
|
||||
'EOR': ['Exclusive Or', [['a', 'b'], ['a^b']], None, ''],
|
||||
'SFT': ['Shift', [['a', 'b^'], ['c']], None, ''],
|
||||
}
|
||||
inst_re = re.compile(r'^([A-Z]{3})(2?k?r?)$')
|
||||
addr_dict = {
|
||||
'.': 'zero-page address',
|
||||
',': 'relative address',
|
||||
';': 'absolute address',
|
||||
':': 'raw address',
|
||||
'\'': 'raw character',
|
||||
'\"': 'raw word',
|
||||
}
|
||||
def _execute(self, w, **vargs):
|
||||
tok = w.get_token()
|
||||
word = tok.string
|
||||
if word is None:
|
||||
w.set_error('no word selected')
|
||||
return
|
||||
m = self.inst_re.match(word)
|
||||
if m and m.group(1) in self.ops:
|
||||
prefix, suffix = m.groups()
|
||||
name, ds, rs, desc = self.ops[prefix]
|
||||
def stk(xs):
|
||||
return ' -- '.join([' '.join(x) for x in xs])
|
||||
if rs is None:
|
||||
msg = '%s (%s) %s: %s' % (word, stk(ds), name, desc)
|
||||
else:
|
||||
msg = '%s (%s) {%s} %s: %s' % (word, stk(ds), stk(rs), name, desc)
|
||||
w.set_error(msg)
|
||||
elif tok.name == 'tal.number':
|
||||
n = int(word[1:], 16)
|
||||
w.set_error('%r is a number (%d)' % (word, n))
|
||||
elif tok.name == 'tal.defmacro':
|
||||
w.set_error('%r is a macro definition' % word)
|
||||
elif tok.name == 'tal.pad':
|
||||
n = int(word[1:], 16)
|
||||
if word[0] == '|':
|
||||
w.set_error('%r is an absolute pad (%d)' % (word, n))
|
||||
else:
|
||||
w.set_error('%r is a relative pad (+%d)' % (word, n))
|
||||
elif tok.name == 'tal.deflabel':
|
||||
w.set_error('%r is a label definition' % word)
|
||||
elif tok.name == 'tal.defsublabel':
|
||||
w.set_error('%r is a sublabel definition' % word)
|
||||
elif tok.name == 'tal.addr':
|
||||
kind = self.addr_dict.get(word[0], 'unknown address')
|
||||
w.set_error('%r is a %s' % (word, kind))
|
||||
else:
|
||||
w.set_error('%r is not recognized' % word)
|
||||
|
||||
|
||||
class Tal(Fundamental):
|
||||
name = 'tal'
|
||||
extensions = ['.tal']
|
||||
grammar = TalGrammar
|
||||
actions = [Taldoc]
|
||||
colors = {
|
||||
'tal.addr': hi_cyan,
|
||||
'tal.defmacro': hi_blue,
|
||||
|
@ -66,11 +160,12 @@ class Tal(Fundamental):
|
|||
'tal.inst': hi_magenta,
|
||||
'tal.deflabel': hi_blue,
|
||||
'tal.defsublabel': hi_cyan,
|
||||
'tal.hex': hi_green,
|
||||
'tal.number': hi_green,
|
||||
'tal.pad': hi_orange,
|
||||
'tal.spacer': hi_orange,
|
||||
}
|
||||
_bindings = {
|
||||
'taldoc': ('C-c p',),
|
||||
'close-paren': (')',),
|
||||
'close-brace': ('}',),
|
||||
'close-bracket': (']',),
|
||||
|
|
Loading…
Reference in New Issue