diff options
author | Eduardo Julian | 2019-06-26 23:48:29 -0400 |
---|---|---|
committer | Eduardo Julian | 2019-06-26 23:48:29 -0400 |
commit | 4f191540f831a7bba0e262b1a6b598f99fb9b35c (patch) | |
tree | f9c3523b9d8ec5f02dd5bf348268dcf39d192f30 /stdlib/source/lux/target/jvm/program.lux | |
parent | 8a65c2faa8b0f038e93536af27940c359eb1d3fd (diff) |
Constant pool support, finished label machinery, and enhanced machinery for writing bytecode instructions.
Diffstat (limited to '')
-rw-r--r-- | stdlib/source/lux/target/jvm/program.lux | 384 |
1 files changed, 366 insertions, 18 deletions
diff --git a/stdlib/source/lux/target/jvm/program.lux b/stdlib/source/lux/target/jvm/program.lux index 9d5dbe06c..673743c73 100644 --- a/stdlib/source/lux/target/jvm/program.lux +++ b/stdlib/source/lux/target/jvm/program.lux @@ -6,23 +6,29 @@ [control ["." state (#+ State)] ["." writer (#+ Writer)] - ["." function]] + ["." function] + ["." exception (#+ exception:)]] [data ["." error (#+ Error)] + [text + ["%" format]] [number ["." nat]] [collection ["." dictionary (#+ Dictionary)]]]] ["." / #_ - ["#." instruction (#+ Instruction) ("#@." monoid)] - [// + ["#." condition (#+ Local)] + ["#." jump (#+ Jump Big-Jump)] + ["#." instruction (#+ Primitive-Array-Type Instruction) ("#@." monoid)] + ["/#" // #_ + ["#." index] [encoding - [unsigned (#+ U2)]]]]) + ["#." unsigned (#+ U1 U2)]] + ["#." constant (#+ UTF8) + ["#/."pool (#+ Pool)]]]]) (type: #export Label Nat) -(type: #export Jump U2) - (type: #export Address Nat) (type: Resolver (Dictionary Label Address)) @@ -65,21 +71,23 @@ (wrap (/instruction@compose left right))))))) (type: #export (Program a) - (State Tracker (Writer Partial a))) + (State [Pool Tracker] (Writer Partial a))) (def: #export new-label (Program Label) - (function (_ tracker) - [(update@ #next-label inc tracker) + (function (_ [pool tracker]) + [[pool + (update@ #next-label inc tracker)] [..partial-identity (get@ #next-label tracker)]])) (def: #export (set-label label) (-> Label (Program Any)) - (function (_ tracker) - [(update@ #known-labels - (dictionary.put label (get@ #program-counter tracker)) - tracker) + (function (_ [pool tracker]) + [[pool + (update@ #known-labels + (dictionary.put label (get@ #program-counter tracker)) + tracker)] [..partial-identity []]])) @@ -88,12 +96,352 @@ ## seems to have a bug that is being triggered here. (:coerce (Monad Program) (writer.with ..partial-monoid - (: (Monad (State Tracker)) + (: (Monad (State [Pool Tracker])) state.monad)))) -(def: #export (resolve program) - (All [a] (-> (Program a) (Error [Instruction a]))) - (let [[tracker [partial output]] (state.run ..fresh program)] +(def: #export (resolve pool program) + (All [a] (-> Pool (Program a) (Error [Pool Instruction a]))) + (let [[[pool tracker] [partial output]] (state.run [pool ..fresh] program)] (do error.monad [instruction (partial (get@ #known-labels tracker))] - (wrap [instruction output])))) + (wrap [pool instruction output])))) + +(def: (nullary instruction) + (-> Instruction (Program Any)) + (function (_ [pool tracker]) + [[pool tracker] + [(function.constant (#error.Success instruction)) + []]])) + +(template [<name> <instruction>] + [(def: #export <name> (nullary <instruction>))] + + [nop /instruction.nop] + [aconst-null /instruction.aconst-null] + + [iconst-m1 /instruction.iconst-m1] + [iconst-0 /instruction.iconst-0] + [iconst-1 /instruction.iconst-1] + [iconst-2 /instruction.iconst-2] + [iconst-3 /instruction.iconst-3] + [iconst-4 /instruction.iconst-4] + [iconst-5 /instruction.iconst-5] + + [lconst-0 /instruction.lconst-0] + [lconst-1 /instruction.lconst-1] + + [fconst-0 /instruction.fconst-0] + [fconst-1 /instruction.fconst-1] + [fconst-2 /instruction.fconst-2] + + [dconst-0 /instruction.dconst-0] + [dconst-1 /instruction.dconst-1] + + [pop /instruction.pop] + [pop2 /instruction.pop2] + + [dup /instruction.dup] + [dup-x1 /instruction.dup-x1] + [dup-x2 /instruction.dup-x2] + [dup2 /instruction.dup2] + [dup2-x1 /instruction.dup2-x1] + [dup2-x2 /instruction.dup2-x2] + + [swap /instruction.swap] + + [istore-0 /instruction.istore-0] + [istore-1 /instruction.istore-1] + [istore-2 /instruction.istore-2] + [istore-3 /instruction.istore-3] + + [lstore-0 /instruction.lstore-0] + [lstore-1 /instruction.lstore-1] + [lstore-2 /instruction.lstore-2] + [lstore-3 /instruction.lstore-3] + + [fstore-0 /instruction.fstore-0] + [fstore-1 /instruction.fstore-1] + [fstore-2 /instruction.fstore-2] + [fstore-3 /instruction.fstore-3] + + [dstore-0 /instruction.dstore-0] + [dstore-1 /instruction.dstore-1] + [dstore-2 /instruction.dstore-2] + [dstore-3 /instruction.dstore-3] + + [astore-0 /instruction.astore-0] + [astore-1 /instruction.astore-1] + [astore-2 /instruction.astore-2] + [astore-3 /instruction.astore-3] + + [iaload /instruction.iaload] + [laload /instruction.laload] + [faload /instruction.faload] + [daload /instruction.daload] + [aaload /instruction.aaload] + [baload /instruction.baload] + [caload /instruction.caload] + [saload /instruction.saload] + + [iastore /instruction.iastore] + [lastore /instruction.lastore] + [fastore /instruction.fastore] + [dastore /instruction.dastore] + [aastore /instruction.aastore] + [bastore /instruction.bastore] + [castore /instruction.castore] + [sastore /instruction.sastore] + + [iadd /instruction.iadd] + [isub /instruction.isub] + [imul /instruction.imul] + [idiv /instruction.idiv] + [irem /instruction.irem] + [ineg /instruction.ineg] + [ishl /instruction.ishl] + [ishr /instruction.ishr] + [iushr /instruction.iushr] + [iand /instruction.iand] + [ior /instruction.ior] + [ixor /instruction.ixor] + + [ladd /instruction.ladd] + [lsub /instruction.lsub] + [lmul /instruction.lmul] + [ldiv /instruction.ldiv] + [lrem /instruction.lrem] + [lneg /instruction.lneg] + [land /instruction.land] + [lor /instruction.lor] + [lxor /instruction.lxor] + + [fadd /instruction.fadd] + [fsub /instruction.fsub] + [fmul /instruction.fmul] + [fdiv /instruction.fdiv] + [frem /instruction.frem] + [fneg /instruction.fneg] + + [dadd /instruction.dadd] + [dsub /instruction.dsub] + [dmul /instruction.dmul] + [ddiv /instruction.ddiv] + [drem /instruction.drem] + [dneg /instruction.dneg] + + [lshl /instruction.lshl] + [lshr /instruction.lshr] + [lushr /instruction.lushr] + + [l2i /instruction.l2i] + [l2f /instruction.l2f] + [l2d /instruction.l2d] + + [f2i /instruction.f2i] + [f2l /instruction.f2l] + [f2d /instruction.f2d] + + [d2i /instruction.d2i] + [d2l /instruction.d2l] + [d2f /instruction.d2f] + + [i2l /instruction.i2l] + [i2f /instruction.i2f] + [i2d /instruction.i2d] + [i2b /instruction.i2b] + [i2c /instruction.i2c] + [i2s /instruction.i2s] + + [lcmp /instruction.lcmp] + + [fcmpl /instruction.fcmpl] + [fcmpg /instruction.fcmpg] + + [dcmpl /instruction.dcmpl] + [dcmpg /instruction.dcmpg] + + [ireturn /instruction.ireturn] + [lreturn /instruction.lreturn] + [freturn /instruction.freturn] + [dreturn /instruction.dreturn] + [areturn /instruction.areturn] + [return /instruction.return] + + [arraylength /instruction.arraylength] + + [athrow /instruction.athrow] + + [monitorenter /instruction.monitorenter] + [monitorexit /instruction.monitorexit] + ) + +(def: #export (bipush byte) + (-> U1 (Program Any)) + (function (_ [pool tracker]) + [[pool tracker] + [(function.constant (#error.Success (/instruction.bipush byte))) + []]])) + +(def: (lift on-pool) + (All [a] + (-> (State Pool a) + (Program a))) + (function (_ [pool tracker]) + (let [[pool' output] (state.run pool on-pool)] + [[pool' tracker] + [..partial-identity + output]]))) + +(def: max-u1 + (|> //unsigned.max-u1 //unsigned.nat //unsigned.u2)) + +(template [<name> <type> <constant> <ldc>] + [(def: #export (<name> value) + (-> <type> (Program Any)) + (do ..monad + [index (..lift (<constant> value)) + #let [index' (//index.number index)]] + (..nullary (if (:: //unsigned.order < ..max-u1 index') + (/instruction.ldc (|> index' //unsigned.nat //unsigned.u1)) + (<ldc> index)))))] + + [ldc/long //constant.Long //constant/pool.long /instruction.ldc2-w/long] + [ldc/double //constant.Double //constant/pool.double /instruction.ldc2-w/double] + ) + +(template [<name> <instruction> <input>] + [(def: #export <name> + (-> <input> (Program Any)) + (|>> <instruction> nullary))] + + [iload /instruction.iload Local] + [lload /instruction.lload Local] + [fload /instruction.fload Local] + [dload /instruction.dload Local] + [aload /instruction.aload Local] + + [istore /instruction.istore Local] + [lstore /instruction.lstore Local] + [fstore /instruction.fstore Local] + [dstore /instruction.dstore Local] + [astore /instruction.astore Local] + + [ret /instruction.ret Local] + + [newarray /instruction.newarray Primitive-Array-Type] + + [sipush /instruction.sipush U2] + ) + +(exception: #export (unknown-label {label Label}) + (exception.report + ["Label" (%.nat label)])) + +(exception: #export (cannot-do-a-big-jump {label Label} + {@from Address} + {jump Big-Jump}) + (exception.report + ["Label" (%.nat label)] + ["Start" (%.nat @from)] + ["Target" (|> jump //unsigned.nat .int %.int)])) + +(def: (jump @from @to) + (-> Address Address (Either Jump Big-Jump)) + (let [jump (.int (n/- @to @from)) + big? (n/> (//unsigned.nat //unsigned.max-u2) + (.nat (i/* (if (i/>= +0 jump) + +1 + -1) + jump)))] + (if big? + (#.Right (//unsigned.u4 (.nat jump))) + (#.Left (//unsigned.u2 (.nat jump)))))) + +(template [<name> <instruction>] + [(def: #export (<name> label) + (-> Label (Program Any)) + (function (_ [pool tracker]) + (let [@from (get@ #program-counter tracker)] + [[pool tracker] + [(function (_ resolver) + (case (dictionary.get label resolver) + (#.Some @to) + (case (jump @from @to) + (#.Left jump) + (#error.Success (<instruction> jump)) + + (#.Right jump) + (exception.throw ..cannot-do-a-big-jump [label @from jump])) + + #.None + (exception.throw ..unknown-label [label]))) + []]])))] + + [ifeq /instruction.ifeq] + [ifne /instruction.ifne] + [iflt /instruction.iflt] + [ifge /instruction.ifge] + [ifgt /instruction.ifgt] + [ifle /instruction.ifle] + + [if-icmpeq /instruction.if-icmpeq] + [if-icmpne /instruction.if-icmpne] + [if-icmplt /instruction.if-icmplt] + [if-icmpge /instruction.if-icmpge] + [if-icmpgt /instruction.if-icmpgt] + [if-icmple /instruction.if-icmple] + + [if-acmpeq /instruction.if-acmpeq] + [if-acmpne /instruction.if-acmpne] + + [ifnull /instruction.ifnull] + [ifnonnull /instruction.ifnonnull] + ) + +(template [<name> <normal-instruction> <wide-instruction>] + [(def: #export (<name> label) + (-> Label (Program Any)) + (function (_ [pool tracker]) + (let [@from (get@ #program-counter tracker)] + [[pool tracker] + [(function (_ resolver) + (case (dictionary.get label resolver) + (#.Some @to) + (case (jump @from @to) + (#.Left jump) + (#error.Success (<normal-instruction> jump)) + + (#.Right jump) + (#error.Success (<wide-instruction> jump))) + + #.None + (exception.throw ..unknown-label [label]))) + []]])))] + + [goto /instruction.goto /instruction.goto-w] + [jsr /instruction.jsr /instruction.jsr-w] + ) + +(template [<name> <instruction>] + [(def: #export (<name> class) + (-> UTF8 (Program Any)) + (do ..monad + ## TODO: Make sure it"s impossible to have indexes greater than U2. + [index (..lift (//constant/pool.class class))] + (..nullary (<instruction> index))))] + + [new /instruction.new] + [anewarray /instruction.anewarray] + [checkcast /instruction.checkcast] + [instanceof /instruction.instanceof] + ) + +(def: #export (iinc register increase) + (-> Local U1 (Program Any)) + (..nullary (/instruction.iinc register increase))) + +(def: #export (multianewarray class count) + (-> UTF8 U1 (Program Any)) + (do ..monad + [index (..lift (//constant/pool.class class))] + (..nullary (/instruction.multianewarray index count)))) |