Advertisement
ElvishJerricco

Lasm

Sep 16th, 2013
753
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 23.05 KB | None | 0 0
  1. local language = {
  2.     header = {
  3.         {name="signature", val=0x1B4C7561, size=4},
  4.         {name="version", val=0x51, size=1},
  5.         {name="format", val=0x00, size=1},
  6.         {name="endianness", val=0x00, size=1},
  7.         {name="size_int", val=0x04, size=1},
  8.         {name="size_t", val=0x04, size=1},
  9.         {name="size_inst", val=0x04, size=1},
  10.         {name="lua_Number", val=0x08, size=1},
  11.         {name="integral", val=0x00, size=1}
  12.     },
  13.     symbols = {
  14.         ["&"] = true
  15.     },
  16.     keywords = {
  17.         [".local"] = true, --
  18.         [".const"] = true, --
  19.         [".param"] = true, --
  20.         [".vararg"] = true, --
  21.         [".upval"] = true, --
  22.         [".end"] = true, --
  23.         [".function"] = true, --
  24.         [".stacksize"] = true
  25.     },
  26.     opcodes = {
  27.         NOT = {
  28.             type = "iABC",
  29.             arguments = {
  30.                 {
  31.                     type = "R",
  32.                     index = "A"
  33.                 },
  34.                 {
  35.                     type = "R",
  36.                     index = "B"
  37.                 }
  38.             },
  39.             code = 19
  40.         },
  41.         LOADK = {
  42.             type = "iABx",
  43.             arguments = {
  44.                 {
  45.                     type = "R",
  46.                     index = "A"
  47.                 },
  48.                 {
  49.                     type = "C",
  50.                     index = "Bx"
  51.                 }
  52.             },
  53.             code = 1
  54.         },
  55.         SETTABLE = {
  56.             type = "iABC",
  57.             arguments = {
  58.                 {
  59.                     type = "R",
  60.                     index = "A"
  61.                 },
  62.                 {
  63.                     type = "RK",
  64.                     index = "B"
  65.                 },
  66.                 {
  67.                     type = "RK",
  68.                     index = "C"
  69.                 }
  70.             },
  71.             code = 9
  72.         },
  73.         CLOSE = {
  74.             type = "iABC",
  75.             arguments = {
  76.                 {
  77.                     type = "R",
  78.                     index = "A"
  79.                 }
  80.             },
  81.             code = 35
  82.         },
  83.         GETTABLE = {
  84.             type = "iABC",
  85.             arguments = {
  86.                 {
  87.                     type = "R",
  88.                     index = "A"
  89.                 },
  90.                 {
  91.                     type = "R",
  92.                     index = "B"
  93.                 },
  94.                 {
  95.                     type = "RK",
  96.                     index = "C"
  97.                 }
  98.             },
  99.             code = 6
  100.         },
  101.         DIV = {
  102.             type = "iABC",
  103.             arguments = {
  104.                 {
  105.                     type = "R",
  106.                     index = "A"
  107.                 },
  108.                 {
  109.                     type = "RK",
  110.                     index = "B"
  111.                 },
  112.                 {
  113.                     type = "RK",
  114.                     index = "C"
  115.                 }
  116.             },
  117.             code = 15
  118.         },
  119.         TEST = {
  120.             type = "iABC",
  121.             arguments = {
  122.                 {
  123.                     type = "R",
  124.                     index = "A"
  125.                 },
  126.                 {
  127.                     type = "N",
  128.                     index = "C"
  129.                 }
  130.             },
  131.             code = 26
  132.         },
  133.         ADD = {
  134.             type = "iABC",
  135.             arguments = {
  136.                 {
  137.                     type = "R",
  138.                     index = "A"
  139.                 },
  140.                 {
  141.                     type = "RK",
  142.                     index = "B"
  143.                 },
  144.                 {
  145.                     type = "RK",
  146.                     index = "C"
  147.                 }
  148.             },
  149.             code = 12
  150.         },
  151.         SETLIST = {
  152.             type = "iABC",
  153.             arguments = {
  154.                 {
  155.                     type = "R",
  156.                     index = "A"
  157.                 },
  158.                 {
  159.                     type = "N",
  160.                     index = "B"
  161.                 },
  162.                 {
  163.                     type = "N",
  164.                     index = "C"
  165.                 }
  166.             },
  167.             code = 34
  168.         },
  169.         TFORLOOP = {
  170.             type = "iABC",
  171.             arguments = {
  172.                 {
  173.                     type = "R",
  174.                     index = "A"
  175.                 },
  176.                 {
  177.                     type = "N",
  178.                     index = "C"
  179.                 }
  180.             },
  181.             code = 33
  182.         },
  183.         LOADBOOL = {
  184.             type = "iABC",
  185.             arguments = {
  186.                 {
  187.                     type = "R",
  188.                     index = "A"
  189.                 },
  190.                 {
  191.                     type = "N",
  192.                     index = "B"
  193.                 },
  194.                 {
  195.                     type = "N",
  196.                     index = "C"
  197.                 }
  198.             },
  199.             code = 2
  200.         },
  201.         TESTSET = {
  202.             type = "iABC",
  203.             arguments = {
  204.                 {
  205.                     type = "R",
  206.                     index = "A"
  207.                 },
  208.                 {
  209.                     type = "R",
  210.                     index = "B"
  211.                 },
  212.                 {
  213.                     type = "N",
  214.                     index = "C"
  215.                 }
  216.             },
  217.             code = 27
  218.         },
  219.         FORLOOP = {
  220.             type = "iAsBx",
  221.             arguments = {
  222.                 {
  223.                     type = "R",
  224.                     index = "A"
  225.                 },
  226.                 {
  227.                     type = "N",
  228.                     index = "sBx"
  229.                 }
  230.             },
  231.             code = 31
  232.         },
  233.         UNM = {
  234.             type = "iABC",
  235.             arguments = {
  236.                 {
  237.                     type = "R",
  238.                     index = "A"
  239.                 },
  240.                 {
  241.                     type = "R",
  242.                     index = "B"
  243.                 }
  244.             },
  245.             code = 18
  246.         },
  247.         CALL = {
  248.             type = "iABC",
  249.             arguments = {
  250.                 {
  251.                     type = "R",
  252.                     index = "A"
  253.                 },
  254.                 {
  255.                     type = "N",
  256.                     index = "B"
  257.                 },
  258.                 {
  259.                     type = "N",
  260.                     index = "C"
  261.                 }
  262.             },
  263.             code = 28
  264.         },
  265.         EQ = {
  266.             type = "iABC",
  267.             arguments = {
  268.                 {
  269.                     type = "R",
  270.                     index = "A"
  271.                 },
  272.                 {
  273.                     type = "RK",
  274.                     index = "B"
  275.                 },
  276.                 {
  277.                     type = "RK",
  278.                     index = "C"
  279.                 }
  280.             },
  281.             code = 23
  282.         },
  283.         LT = {
  284.             type = "iABC",
  285.             arguments = {
  286.                 {
  287.                     type = "R",
  288.                     index = "A"
  289.                 },
  290.                 {
  291.                     type = "RK",
  292.                     index = "B"
  293.                 },
  294.                 {
  295.                     type = "RK",
  296.                     index = "C"
  297.                 }
  298.             },
  299.             code = 24
  300.         },
  301.         RETURN = {
  302.             type = "iABC",
  303.             arguments = {
  304.                 {
  305.                     type = "R",
  306.                     index = "A"
  307.                 },
  308.                 {
  309.                     type = "N",
  310.                     index = "B"
  311.                 }
  312.             },
  313.             code = 30
  314.         },
  315.         JMP = {
  316.             type = "iAsBx",
  317.             arguments = {
  318.                 {
  319.                     type = "N",
  320.                     index = "sBx"
  321.                 }
  322.             },
  323.             code = 22
  324.         },
  325.         CLOSURE = {
  326.             type = "iABx",
  327.             arguments = {
  328.                 {
  329.                     type = "R",
  330.                     index = "A"
  331.                 },
  332.                 {
  333.                     type = "P",
  334.                     index = "Bx"
  335.                 }
  336.             },
  337.             code = 36
  338.         },
  339.         SETGLOBAL = {
  340.             type = "iABx",
  341.             arguments = {
  342.                 {
  343.                     type = "R",
  344.                     index = "A"
  345.                 },
  346.                 {
  347.                     type = "C",
  348.                     index = "Bx"
  349.                 }
  350.             },
  351.             code = 7
  352.         },
  353.         MUL = {
  354.             type = "iABC",
  355.             arguments = {
  356.                 {
  357.                     type = "R",
  358.                     index = "A"
  359.                 },
  360.                 {
  361.                     type = "RK",
  362.                     index = "B"
  363.                 },
  364.                 {
  365.                     type = "RK",
  366.                     index = "C"
  367.                 }
  368.             },
  369.             code = 14
  370.         },
  371.         TAILCALL = {
  372.             type = "iABC",
  373.             arguments = {
  374.                 {
  375.                     type = "R",
  376.                     index = "A"
  377.                 },
  378.                 {
  379.                     type = "N",
  380.                     index = "B"
  381.                 }
  382.             },
  383.             code = 29
  384.         },
  385.         POW = {
  386.             type = "iABC",
  387.             arguments = {
  388.                 {
  389.                     type = "R",
  390.                     index = "A"
  391.                 },
  392.                 {
  393.                     type = "RK",
  394.                     index = "B"
  395.                 },
  396.                 {
  397.                     type = "RK",
  398.                     index = "C"
  399.                 }
  400.             },
  401.             code = 17
  402.         },
  403.         CONCAT = {
  404.             type = "iABC",
  405.             arguments = {
  406.                 {
  407.                     type = "R",
  408.                     index = "A"
  409.                 },
  410.                 {
  411.                     type = "R",
  412.                     index = "B"
  413.                 },
  414.                 {
  415.                     type = "R",
  416.                     index = "C"
  417.                 }
  418.             },
  419.             code = 21
  420.         },
  421.         GETUPVAL = {
  422.             type = "iABC",
  423.             arguments = {
  424.                 {
  425.                     type = "R",
  426.                     index = "A"
  427.                 },
  428.                 {
  429.                     type = "U",
  430.                     index = "B"
  431.                 }
  432.             },
  433.             code = 4
  434.         },
  435.         NEWTABLE = {
  436.             type = "iABC",
  437.             arguments = {
  438.                 {
  439.                     type = "R",
  440.                     index = "A"
  441.                 },
  442.                 {
  443.                     type = "N",
  444.                     index = "B"
  445.                 },
  446.                 {
  447.                     type = "N",
  448.                     index = "C"
  449.                 }
  450.             },
  451.             code = 10
  452.         },
  453.         SETUPVAL = {
  454.             type = "iABC",
  455.             arguments = {
  456.                 {
  457.                     type = "R",
  458.                     index = "A"
  459.                 },
  460.                 {
  461.                     type = "U",
  462.                     index = "B"
  463.                 }
  464.             },
  465.             code = 8
  466.         },
  467.         SELF = {
  468.             type = "iABC",
  469.             arguments = {
  470.                 {
  471.                     type = "R",
  472.                     index = "A"
  473.                 },
  474.                 {
  475.                     type = "R",
  476.                     index = "B"
  477.                 },
  478.                 {
  479.                     type = "RK",
  480.                     index = "C"
  481.                 }
  482.             },
  483.             code = 11
  484.         },
  485.         SUB = {
  486.             type = "iABC",
  487.             arguments = {
  488.                 {
  489.                     type = "R",
  490.                     index = "A"
  491.                 },
  492.                 {
  493.                     type = "RK",
  494.                     index = "B"
  495.                 },
  496.                 {
  497.                     type = "RK",
  498.                     index = "C"
  499.                 }
  500.             },
  501.             code = 13
  502.         },
  503.         LOADNIL = {
  504.             type = "iABC",
  505.             arguments = {
  506.                 {
  507.                     type = "R",
  508.                     index = "A"
  509.                 },
  510.                 {
  511.                     type = "R",
  512.                     index = "B"
  513.                 }
  514.             },
  515.             code = 3
  516.         },
  517.         LEN = {
  518.             type = "iABC",
  519.             arguments = {
  520.                 {
  521.                     type = "R",
  522.                     index = "A"
  523.                 },
  524.                 {
  525.                     type = "R",
  526.                     index = "B"
  527.                 }
  528.             },
  529.             code = 20
  530.         },
  531.         FORPREP = {
  532.             type = "iAsBx",
  533.             arguments = {
  534.                 {
  535.                     type = "R",
  536.                     index = "A"
  537.                 },
  538.                 {
  539.                     type = "N",
  540.                     index = "sBx"
  541.                 }
  542.             },
  543.             code = 32
  544.         },
  545.         MOD = {
  546.             type = "iABC",
  547.             arguments = {
  548.                 {
  549.                     type = "R",
  550.                     index = "A"
  551.                 },
  552.                 {
  553.                     type = "RK",
  554.                     index = "B"
  555.                 },
  556.                 {
  557.                     type = "RK",
  558.                     index = "C"
  559.                 }
  560.             },
  561.             code = 16
  562.         },
  563.         VARARG = {
  564.             type = "iABC",
  565.             arguments = {
  566.                 {
  567.                     type = "R",
  568.                     index = "A"
  569.                 },
  570.                 {
  571.                     type = "N",
  572.                     index = "B"
  573.                 }
  574.             },
  575.             code = 37
  576.         },
  577.         MOVE = {
  578.             type = "iABC",
  579.             arguments = {
  580.                 {
  581.                     type = "R",
  582.                     index = "A"
  583.                 },
  584.                 {
  585.                     type = "R",
  586.                     index = "B"
  587.                 }
  588.             },
  589.             code = 0
  590.         },
  591.         LE = {
  592.             type = "iABC",
  593.             arguments = {
  594.                 {
  595.                     type = "R",
  596.                     index = "A"
  597.                 },
  598.                 {
  599.                     type = "RK",
  600.                     index = "B"
  601.                 },
  602.                 {
  603.                     type = "RK",
  604.                     index = "C"
  605.                 }
  606.             },
  607.             code = 25
  608.         },
  609.         GETGLOBAL = {
  610.             type = "iABx",
  611.             arguments = {
  612.                 {
  613.                     type = "R",
  614.                     index = "A"
  615.                 },
  616.                 {
  617.                     type = "C",
  618.                     index = "Bx"
  619.                 }
  620.             },
  621.             code = 5
  622.         }
  623.     }
  624. }
  625.  
  626. local function compileparsed( ... )
  627.     local parsed = ({ ... })[1]
  628.     local lookup = {}
  629.     local out = ""
  630.     local compileFunction -- declare here so that all functions can access it. Weird local rules
  631.  
  632.     local function compile(s)
  633.         out = out .. s
  634.     end
  635.  
  636.     local function numToByteString(n, bytes, forceBigEndian)
  637.         if lookup.endianness == 0 or forceBigEndian then
  638.             for i=bytes-1, 0, -1 do
  639.                 local byte = bit.band(bit.brshift(n, i * 8), 0xff)
  640.                 compile(string.char(byte))
  641.             end
  642.         elseif lookup.endianness == 1 then
  643.             for i=0, bytes - 1 do
  644.                 local byte = bit.band(bit.brshift(n, i * 8), 0xff)
  645.                 compile(string.char(byte))
  646.             end
  647.         else
  648.             error("Unsupported endianness:" .. tostring(lookup.endianness))
  649.         end
  650.     end
  651.  
  652.  
  653.  
  654.     local function compileByte(b)
  655.         compile(string.char(b))
  656.     end
  657.  
  658.     local function compileInteger(n)
  659.         numToByteString(n, lookup.size_int)
  660.     end
  661.  
  662.     local function compileString(s)
  663.         numToByteString(#s + 1, lookup.size_t)
  664.         compile(s .. "\0")
  665.     end
  666.  
  667.     local function compileNumber(n)
  668.         assert(lookup.lua_Number == 8, "Unsupported lua_Number size")
  669.         local frac = n - math.floor(n)
  670.         local whole = n - frac
  671.  
  672.         local function wholeToBin(whole)
  673.             local bWhole = ""
  674.             repeat
  675.                 bWhole = bWhole .. (whole % 2)
  676.                 whole = math.floor(whole / 2)
  677.             until whole == 0
  678.             return bWhole:reverse()
  679.         end
  680.         local bWhole = wholeToBin(whole)
  681.  
  682.         local bFrac = ""
  683.         while frac ~= 0 do
  684.             frac = frac * 2
  685.             if frac >= 1 then
  686.                 frac = frac - 1
  687.                 bFrac = bFrac .. "1"
  688.             else
  689.                 bFrac = bFrac .. "0"
  690.             end
  691.         end
  692.         bWhole = bWhole:gsub("^0*", "")
  693.         bFrac = bFrac:gsub("0*$", "")
  694.         if bWhole .. bFrac == "" then
  695.             for i=1,lookup.lua_Number do compileByte(0) end
  696.             return
  697.         end
  698.         local ex = #bWhole - 1
  699.         local final
  700.         if ex < 0 then
  701.             ex = -bFrac:find("1")
  702.             final = bFrac:sub(-ex + 1)
  703.         else
  704.             final = bWhole:sub(2) .. bFrac
  705.         end
  706.  
  707.         local sign = (n >= 0 and "0" or "1")
  708.         local sEx --[[ hehe ]] = wholeToBin(ex + 1023)
  709.         sEx = ("0"):rep(11 - #sEx) .. sEx
  710.         final = final .. ("0"):rep(52 - #final)
  711.         local fBin = sign .. sEx .. final
  712.         for i=1, lookup.lua_Number * 8, 8 do
  713.             local byte = tonumber(fBin:sub(i, i + 7), 2)
  714.             compileByte(byte)
  715.         end
  716.     end
  717.  
  718.     local function compileBoolean(b)
  719.         compileByte(b)
  720.     end
  721.  
  722.  
  723.  
  724.     local function compileInstructions(f)
  725.         compileInteger(#(f.instructions))
  726.         for i,v in ipairs(f.instructions) do
  727.             local inst = 0
  728.             inst = bit.bor(inst, v.code)
  729.             if not v.A then v.A = 0 end
  730.  
  731.             inst = bit.bor(inst, bit.blshift(v.A, 6))
  732.  
  733.             if v.type == "iABC" then
  734.                 if not v.B then v.B = 0 end
  735.                 if not v.C then v.C = 0 end
  736.  
  737.                 inst = bit.bor(inst, bit.blshift(v.B, 23))
  738.                 inst = bit.bor(inst, bit.blshift(v.C, 14))
  739.             elseif v.type == "iABx" then
  740.                 if not v.Bx then v.Bx = 0 end
  741.                 inst = bit.bor(inst, bit.blshift(v.Bx, 14))
  742.             elseif v.type == "iAsBx" then
  743.                 if not v.sBx then v.sBx = 0 end
  744.                 v.sBx = 131071 + v.sBx -- 131071 = bit.brshift(2^18, 1)
  745.                 inst = b.bor(inst, bit.blshift(v.sBx, 14))
  746.             end
  747.             numToByteString(inst, lookup.size_inst)
  748.         end
  749.     end
  750.  
  751.     local function compileConstants(f)
  752.         compileInteger(#(f.constants))
  753.         for i,v in ipairs(f.constants) do
  754.             if v.type == "boolean" then
  755.                 compileByte(1)
  756.                 compileBoolean(v.data)
  757.             elseif v.type == "number" then
  758.                 compileByte(3)
  759.                 compileNumber(v.data)
  760.             elseif v.type == "string" then
  761.                 compileByte(4)
  762.                 compileString(v.data)
  763.             end
  764.         end
  765.     end
  766.  
  767.     local function compileFunctionProtos(f)
  768.         compileInteger(#(f.prototypes))
  769.         for i,v in ipairs(f.prototypes) do
  770.             compileFunction(v)
  771.         end
  772.     end
  773.  
  774.     local function compileLinePositions(f)
  775.         compileInteger(#(f.instructions))
  776.         for i,v in ipairs(f.instructions) do
  777.             compileInteger(v.line)
  778.         end
  779.     end
  780.  
  781.     local function compileLocals(f)
  782.         compileInteger(#(f.locals))
  783.         for i,v in ipairs(f.locals) do
  784.             compileString(v)
  785.             if i <= f.numParams then
  786.                 compileInteger(0)
  787.             else
  788.                 compileInteger(1)
  789.             end
  790.             compileInteger(#(f.instructions) - 1)
  791.         end
  792.     end
  793.  
  794.     local function compileUpvalues(f)
  795.         compileInteger(#(f.upvalues))
  796.         for i,v in ipairs(f.upvalues) do
  797.             compileString(v)
  798.         end
  799.     end
  800.  
  801.     local function compileFunction(func)
  802.         numToByteString(0, lookup.size_int)
  803.         compileInteger(func.lineDefined)
  804.         compileInteger(func.lastLineDefined)
  805.         compileByte(#(func.upvalues))
  806.         compileByte(func.numParams)
  807.         compileByte(func.vararg)
  808.         compileByte(func.stacksize)
  809.  
  810.         compileInstructions(func)
  811.         compileConstants(func)
  812.         compileFunctionProtos(func)
  813.         compileLinePositions(func)
  814.         compileLocals(func)
  815.         compileUpvalues(func)
  816.     end
  817.  
  818.  
  819.     for i,v in ipairs(language.header) do
  820.         numToByteString(v.val, v.size, true)
  821.         lookup[v.name] = v.val
  822.     end
  823.     compileFunction(parsed)
  824.  
  825.     return out
  826. end
  827.  
  828. local function lexstring( ... )
  829.     ------------------------------------------------------------------
  830.     --                     lexstring.function                       --
  831.     ------------------------------------------------------------------
  832.     --[[
  833.     lexstring.function takes a string argument and returns a table of tokens
  834.     token = {
  835.                 type= type of data,
  836.                 data= the text of the data,
  837.                 base= if type is number, the base for the number system,
  838.                 quoteType= if type is string, the type of quote used
  839.             }
  840.     ]]
  841.  
  842.     ------------------------------------------------------------------ variables
  843.  
  844.     local src = ({ ... })[1]
  845.     local tokens = {}
  846.     local line = 1
  847.  
  848.     local function isWhite()
  849.         return src:find("^%s") == 1 or src:find("^%-%-") == 1
  850.     end
  851.  
  852.     local function isNumber(_src)
  853.         return src:find("^[%d+-]") == 1
  854.     end
  855.  
  856.     local function isString()
  857.         return src:find("^['\"]") == 1 or src:find("^%[=*%[") == 1
  858.     end
  859.  
  860.     local function isBoolean()
  861.         return src:find("^true") == 1 or src:find("^false") == 1
  862.     end
  863.  
  864.     local function isKeyword()
  865.         local str = src:match("^.%a+")
  866.         if not str then return false end
  867.         return language.keywords[str:lower()] and true or false
  868.     end
  869.  
  870.     local function isInstruction()
  871.         local str = src:match("^%a+")
  872.         if not str then return false end
  873.         return language.opcodes[str:upper()] and true or false
  874.     end
  875.  
  876.     local function isAssignment()
  877.         return src:find("^%%%w+") == 1
  878.     end
  879.  
  880.     local function isSymbol()
  881.         return language.symbols[src:sub(1,1)]
  882.     end
  883.  
  884.  
  885.  
  886.     while src ~= "" do
  887.         local token = {line=line}
  888.        
  889.         -- leading whitespaces
  890.         if isWhite() then
  891.             local removed = ""
  892.             src = src:gsub("^%s*", function(w)
  893.                 removed = removed .. w
  894.                 return ""
  895.             end)
  896.             src = src:gsub("^(%-%-%[(=*)%[.*%]%2%])", function(comment)
  897.                 removed = removed .. comment
  898.                 return ""
  899.             end)
  900.             src = src:gsub("^%-%-[^\n]*", function(comment)
  901.                 removed = removed .. comment
  902.                 return ""
  903.             end)
  904.             local _, removedLines = removed:gsub("\n", "")
  905.             line = line + removedLines
  906.         elseif isNumber() then
  907.             local dat = ""
  908.             src = src:gsub("^[+-]", function(sign)
  909.                 dat = dat .. sign
  910.                 return ""
  911.             end)
  912.  
  913.             local base
  914.             for k,v in pairs({[16] = "^0[xX]%x+", [2] = "^0[bB][01]+", [8] = "^0[oO][0-7]+"}) do
  915.                 src = src:gsub(v, function(num)
  916.                     dat = dat .. num
  917.                     base = k
  918.                     return ""
  919.                 end)
  920.             end
  921.             if not base then
  922.                 -- decimal number for sure
  923.                 src = src:gsub("^%d+%.?%d*", function(num)
  924.                     dat = dat .. num
  925.                     base = 10
  926.                     return ""
  927.                 end)
  928.             end
  929.             assert(base and src:find("^%w") ~= 1, "Malformed number at line: " .. line)
  930.             token.type = "number"
  931.             token.data = dat
  932.             token.base = base
  933.         elseif isString() then
  934.             -- string
  935.             local dat
  936.             local quoteType
  937.             src = src:gsub("^((['\"])[^\n]-%2)", function(str, _quoteType)
  938.                 dat = str
  939.                 quoteType = _quoteType
  940.                 return ""
  941.             end)
  942.             if not dat then
  943.                 src = src:gsub("^(%[(=*)%[.-%]%2%])", function(str, levels)
  944.                     dat = str
  945.                     local _, newLines = str:gsub("\n", "")
  946.                     line = line + newLines
  947.                     quoteType = "[" .. levels .. "["
  948.                     return ""
  949.                 end)
  950.             end
  951.             assert(dat, "Malformed string at line: " .. line)
  952.             token.type = "string"
  953.             token.data = dat
  954.             token.quoteType = quoteType
  955.         elseif isBoolean() then
  956.             token.type = "boolean"
  957.             if src:find("^true") then
  958.                 src = src:sub(5)
  959.                 token.data = "true"
  960.             else
  961.                 src = src:sub(6)
  962.                 token.data = "false"
  963.             end
  964.         elseif isKeyword() then
  965.             src = src:gsub("^.%a+", function(w)
  966.                 token.type = "keyword"
  967.                 token.data = w
  968.                 return ""
  969.             end)
  970.         elseif isInstruction() then
  971.             src = src:gsub("^%a+", function(w)
  972.                 token.type = "instruction"
  973.                 token.data = w
  974.                 return ""
  975.             end)
  976.         elseif isAssignment() then
  977.             src = src:gsub("^%%%w+", function(w)
  978.                 token.type = "assignment"
  979.                 token.data = w
  980.                 return ""
  981.             end)
  982.         elseif isSymbol() then
  983.             token.type = "symbol"
  984.             token.data = src:sub(1,1)
  985.             src = src:sub(2)
  986.         else
  987.             error("Unexpected token: " .. src:match("^%.-%s?") .. " at line: " .. line)
  988.         end
  989.  
  990.         if token.type then
  991.             table.insert(tokens, token)
  992.         end
  993.     end
  994.  
  995.     return tokens
  996. end
  997.  
  998. local function loadfile( ... )
  999.     local path = ({ ... })[1]
  1000.     local f = assert(fs.open(path, "r"))
  1001.     return loadstring(f.readAll(), fs.getName(path))
  1002. end
  1003.  
  1004. local function loadstring( ... )
  1005.     local args = { ... }
  1006.     assert(type(args[1]) == "string" and type(args[2]) == "string", "Expected string, string", 2)
  1007.     local str
  1008.     local ok, err = pcall(function()
  1009.         str = compileparsed(parselexed(lexstring(args[1])))
  1010.     end)
  1011.     if not ok then
  1012.         return ok, err
  1013.     end
  1014.  
  1015.     local f
  1016.     f, err = _G.loadstring(str, args[2])
  1017.  
  1018.     return f, err
  1019. end
  1020.  
  1021. local function parselexed( ... )
  1022.     local loadstring = _G.loadstring -- would prefer to use this for string loading, since i have control over the strings.
  1023.     local tokens = ({ ... })[1]
  1024.     -- fix no function declaration for top level
  1025.     --table.insert(tokens, 1, {type="keyword", data=".function"})
  1026.     -- don't need .function because we just need the terminator
  1027.  
  1028.     if #tokens > 0 then
  1029.         local line = tokens[#tokens].line + 1
  1030.         table.insert(tokens, {type="keyword", data=".end", line=line})
  1031.     end
  1032.  
  1033.     local function parseFunction(parent, lineDefined)
  1034.         local func = {}
  1035.         func.assignments = {}
  1036.  
  1037.         func.lineDefined = lineDefined
  1038.         func.numParams = 0
  1039.         func.vararg = 2
  1040.         func.stacksize = nil
  1041.  
  1042.         func.instructions = {}
  1043.         func.constants = {}
  1044.         func.prototypes = {}
  1045.         func.linePositions = {}
  1046.         func.locals = {}
  1047.         func.upvalues = {}
  1048.        
  1049.         -- put parse functions here so they have proper assignment access.
  1050.         local function parseNumberToken(t) -- numbers
  1051.             assert(t.type == "number", "Number expected: " .. t.line)
  1052.             local sNum = t.data
  1053.             if t.base ~= 10 then
  1054.                 sNum = sNum:sub(3)
  1055.             end
  1056.             return tonumber(sNum, t.base)
  1057.         end
  1058.  
  1059.         local function parseStringToken(t)
  1060.             assert(t.type == "string", "String expected: " .. t.line)
  1061.             return assert(_G.loadstring("return " .. t.data, "doesn'tmatter"))()
  1062.         end
  1063.  
  1064.         local function parseConstantToken(t)
  1065.             if t.type == "string" then
  1066.                 return parseStringToken(t), "string"
  1067.             elseif t.type == "number" then
  1068.                 return parseNumberToken(t), "number"
  1069.             elseif t.type == "boolean" then
  1070.                 return (t.data == "true" and 1 or 0), "boolean"
  1071.             else
  1072.                 error("Expected constant on line: " .. t.line)
  1073.             end
  1074.         end
  1075.  
  1076.         local function parseInstruction(inst) -- instructions
  1077.             local opInfo = language.opcodes[inst]
  1078.             local args = {code=opInfo.code, type=opInfo.type}
  1079.             for i=1, #(opInfo.arguments) do
  1080.                 local t = table.remove(tokens, 1)
  1081.                 assert(t.type == "number" or t.type == "assignment" or t.type == "symbol", "Expected argument on line: " .. t.line)
  1082.                 local number
  1083.                 if t.type == "assignment" then
  1084.                     assert(func.assignments[t.data], "Nonexistent assignment used on line: " .. t.line)
  1085.                     assert(func.assignments[t.data].type == opInfo.arguments[i].type, t.line .. ": expected " .. opInfo.arguments[i].type .. ", got " .. func.assignments[t.data].type)
  1086.                     number = func.assignments[t.data].value
  1087.                 elseif t.type == "symbol" and t.data == "&" and (opInfo.arguments[i].type == "C" or opInfo.arguments[i].type == "RK") then
  1088.                     local c, cType = parseConstantToken(table.remove(tokens, 1))
  1089.                     number = #(func.constants) + (opInfo.arguments[i].type == "RK" and 256 or 0)
  1090.                     table.insert(func.constants, {type=cType, data=c})
  1091.                 else
  1092.                     number = parseNumberToken(t)
  1093.                 end
  1094.                 args[opInfo.arguments[i].index] = number
  1095.             end
  1096.             return args
  1097.         end
  1098.  
  1099.  
  1100.  
  1101.  
  1102.  
  1103.  
  1104.         for t in function() return table.remove(tokens, 1) end do
  1105.             if t.type == "instruction" then
  1106.                 local inst = parseInstruction(t.data:upper())
  1107.                 inst.line = t.line
  1108.                 table.insert(func.instructions, inst)
  1109.             elseif t.type == "keyword" then
  1110.                 if t.data == ".end" then
  1111.                     func.lastLineDefined = t.line
  1112.                     local returnInfo = language.opcodes.RETURN
  1113.                     table.insert(func.instructions, {code=returnInfo.code, type=returnInfo.type, A=0, B=1, line=t.line})
  1114.                     break
  1115.                 elseif t.data == ".function" then
  1116.                     if tokens[1] and tokens[1].type == "string" then
  1117.                         func.assignments["%" .. parseStringToken(table.remove(tokens, 1))] = {value = #(func.prototypes), type = "P"}
  1118.                     end
  1119.                     table.insert(func.prototypes, parseFunction(func, t.line))
  1120.                 elseif t.data == ".param" then
  1121.                     assert(func.numParams == #(func.locals), "Local cannot be declared before parameter on line: " .. t.line)
  1122.                     local name = parseStringToken(table.remove(tokens, 1))
  1123.                     func.assignments["%" .. name] = {value = #(func.locals), type = "R"}
  1124.                     table.insert(func.locals, name)
  1125.                     func.numParams = func.numParams + 1
  1126.                 elseif t.data == ".vararg" then
  1127.                     func.vararg = parseNumberToken(table.remove(tokens, 1))
  1128.                 elseif t.data == ".const" then
  1129.                     local c, cType = parseConstantToken(table.remove(tokens, 1))
  1130.                     table.insert(func.constants, {type=cType, data=c})
  1131.                 elseif t.data == ".upval" then
  1132.                     local name = parseStringToken(table.remove(tokens, 1))
  1133.                     func.assignments["%" .. name] = {value = #(func.upvalues), type = "U"}
  1134.                     table.insert(func.upvalues, name)
  1135.                 elseif t.data == ".local" then
  1136.                     local name = parseStringToken(table.remove(tokens, 1))
  1137.                     func.assignments["%" .. name] = {value = #(func.locals), type = "R"}
  1138.                     table.insert(func.locals, name)
  1139.                 elseif t.data == ".stacksize" then
  1140.                     func.stacksize = parseNumberToken(table.remove(tokens, 1))
  1141.                 end
  1142.             else
  1143.                 error("Unexpected token on line: " .. t.line)
  1144.             end
  1145.         end
  1146.         assert(func.stacksize, "Must specify stack size")
  1147.         return func
  1148.     end
  1149.  
  1150.     local top = parseFunction(nil, 0)
  1151.     top.lastLineDefined = 0 -- standard for top level func
  1152.     return top
  1153. end
  1154.  
  1155. local tArgs = { ... }
  1156. assert(tArgs[1] ~= nil, "Input file expected")
  1157. local path = fs.combine(shell.dir(), tArgs[1])
  1158. local src = assert(fs.exists(path) and not fs.isDir(path) and fs.open(path, "r"), "Input file expected").readAll()
  1159. local out = fs.open(fs.combine(shell.dir(), tArgs[2] or "a.out"), "wb")
  1160.  
  1161. local lexed = lexstring(src, path and fs.getName(path) or "lasm")
  1162. local parsed = parselexed(lexed)
  1163. local compiled = compileparsed(parsed)
  1164.  
  1165. local time = os.time()
  1166. for w in compiled:gmatch(".") do
  1167.     if os.time() - time > 0.03 then
  1168.         sleep(0)
  1169.         time = os.time()
  1170.     end
  1171.     out.write(string.byte(w))
  1172. end
  1173. out.close()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement