uxn

Varvara Ordinator, written in ANSI C(SDL2)
git clone https://git.eamoncaddigan.net/uxn.git
Log | Files | Refs | README | LICENSE

uxambly-translate.moon (3874B)


      1 -- Used for porting Uxntal code for use with the old assembler
      2 -- in commit 82f7103a55c21b13f898b20e5d1e174e501bc825 with the
      3 -- assembler that replaced it straight afterwards.
      4 
      5 import P, R, S, C, Ct, Cp, V from require 'lpeg'
      6 
      7 local labels, filename
      8 
      9 opcode_translate =
     10     LDZ2: 'LDA'
     11     STZ2: 'STA'
     12     LDR: 'LDZ2'
     13     STR: 'STZ2'
     14     LDR2: 'LDA2'
     15     STR2: 'STA2'
     16 
     17 grammar = P {
     18     'file'
     19     file: Ct(V'ows' * (V'atom' * V'ows') ^ 0) * Cp!
     20     ws: C S' \n\t' ^ 1
     21     ows: C S' \n\t' ^ 0
     22     atom: V'opcode' + V'comment' + V'variable' + V'addr' + V'literal' + V'setter' + V'getter' + V'short' + V'labeldef' + V'relative' + V'sublabel' + V'data' + V'macro' + V'macroref' + V'rawshort'
     23     comment: C P'(' * (1-V'ws'*P')') ^ 0 * V'ws' * P')'
     24     variable: (P';' / -> '@') * C(V'name') * V'ws' * (P'{' / ->'[') * V'ws' * ((P'' / -> '&') * C(V'name') * V'ws' * (P'' / -> '$') * C(V'name') * V'ws') ^ 0 * (P'}' / -> ']') / (...) ->
     25         var = select 2, ...
     26         r, w = if var\sub(1, 1) == var\sub(1, 1)\upper!
     27             ' DEI', ' DEO'
     28         else
     29             ' LDZ', ' STZ'
     30         for i = 7, select('#', ...), 6
     31             k = select i, ...
     32             rr, ww = if '2' == select i + 3, ...
     33                 r .. '2', w .. '2'
     34             else
     35                 r, w
     36             labels['~' .. var .. '.' .. k] = '.' .. var .. '/' .. k .. rr
     37             labels['=' .. var .. '.' .. k] = '.' .. var .. '/' .. k .. ww
     38             if i == 7
     39                 labels['~' .. var] = '.' .. var .. rr
     40                 labels['=' .. var] = '.' .. var .. ww
     41         ...
     42     name: R('az', 'AZ', '09', '__', '--', '++', '**', '//', '??') ^ 1
     43     addr: C(P'|') * (C(V'hex') / (i) ->
     44         if i == '0200'
     45             return '0100'
     46         if i\match '^01..$'
     47             return i\sub 3
     48         return i
     49     )
     50     literal: C P'#' * V'hex'
     51     hex: R('09', 'af', 'AF') ^ 1
     52     setter: C(P'=' * V'label') / (s) ->
     53         if not labels[s]
     54             error 'label not found: %q in %s'\format s, filename
     55         return labels[s]
     56     getter: C(P'~' * V'label') / (s) ->
     57         if not labels[s]
     58             error 'label not found: %q in %s'\format s, filename
     59         return labels[s]
     60     label: R('az', 'AZ', '09', '__', '--', '..', '$$', ']]', '))', '@@', '""', ',,', '##', '||', '{{', '}}', '%%', ';;', '^^', '~~', '==', '//') ^ 1
     61     short: (P',' / -> ';') * (C(V'label') / (s) -> (s\gsub '%$', '&'))
     62     rawshort: (P'.' / -> ':') * (C(V'label') / (s) -> (s\gsub '%$', '&'))
     63     opcode: (C(R'AZ' * R'AZ' * R'AZ' * P'2' ^ -1) / (s) -> opcode_translate[s] or s) * C P'r' ^ -1 * #V'ws'
     64     labeldef: C P'@' * V'label'
     65     relative: (P'^' / -> ',') * (C(V'label') / (s) -> (s\gsub '%$', '&'))
     66     sublabel: (P'$' / -> '&') * (C(V'label') / (s) -> (s\gsub '%$', '&'))
     67     data: C(P'[') * V'ws' * (V'data_item' * V'ws') ^ 0 * C(P']')
     68     macro: C(P'%' * V'name' * V'ws' * P'{') * V'ws' * (V'atom' * V'ows') ^ 0 * C P'}'
     69     macroref: C V'name'
     70     data_item: C(V'hex' * #V'ws') + V'data_string'
     71     data_string: C((1 - S' \n\t') ^ 1 - P']') / (s) -> '"', s
     72 }
     73 
     74 translate = (_filename) ->
     75     filename = _filename
     76     labels = {}
     77     f = assert io.open filename
     78     contents = f\read '*a'
     79     f\close!
     80     t, len = grammar\match contents
     81     if len <= #contents
     82         print '\027[32m%s\027[0;1m%s\027[0m'\format contents\sub(len - 100, len - 1), contents\sub(len, len + 100)
     83         error 'no match'
     84     filename = filename\gsub 'attic', 'auto'
     85     f = assert io.open filename, 'w'
     86     f\write table.concat(t)
     87     f\close!
     88     f = assert io.popen 'bin/assembler %s bin/boot.rom'\format filename
     89     for l in f\lines!
     90         print l
     91         if l == 'Error: Assembly[Failed]'
     92             os.exit 1
     93     f\close!
     94     os.exit 0
     95 
     96 translate 'attic/software/assembler.tal'
     97 os.exit 0
     98 
     99 translate 'attic/tests/opcodes.tal'
    100 translate 'attic/tests/basics.tal'
    101 
    102 -- for k, v in pairs t
    103 --     print k