Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

240
LINES

< > BotCompany Repo | #1034318 // LASToByteCode [works for many language constructs already!]

JavaX fragment (include) [tags: use-pretranspiled]

Uses 679K of libraries. Click here for Pure Java version (27908L/137K).

1  
set flag AllPublic. // so we can access main call()
2  
3  
// functions used in the generated code
4  
please include functions call preciseGetOrCallMethod set.
5  
6  
srecord noeq LASToByteCode(MethodMaker m) {
7  
  bool callPing = true;
8  
  
9  
  replace Tb with GazelleV_LeftArrowScript. // Short for "Toolbox"
10  
  delegate Evaluable to Tb.
11  
  
12  
  // parameter index of VarContext
13  
  settable int iVarContext = -1;
14  
  
15  
  delegate none, objValue, intValue, doubleValue to JVMStackCellType.
16  
  
17  
  delegate convertToObject, discardStackTop, here, loadNull to m.
18  
  
19  
  Tb.Script returnableScript;
20  
  
21  
  settable IF1<JVMStackCellType> postConversion;
22  
  
23  
  JVMStackCellType compileScript(Tb.Script script) {
24  
    returnableScript = script;
25  
    var stackTop = compile(script);
26  
    if (postConversion != null)
27  
      stackTop = postConversion.get(stackTop);
28  
    ret stackTop;
29  
  }
30  
  
31  
  void compileToObject(Tb.Evaluable code) {
32  
    convertToObject(compile(code));
33  
  }
34  
35  
  JVMStackCellType compile(Tb.Evaluable code) {
36  
    if (code cast Tb.Const) {
37  
      O o = code.value;
38  
      if (o == null) {
39  
        m.add(new ACONST_NULL);
40  
        ret objValue;
41  
      } else if (o cast S) {
42  
        m.stringConstant(o);
43  
        ret objValue;
44  
      } else if (o cast Int) { m.intConstant(o); ret intValue; }
45  
      else if (o cast Double) { m.doubleConstant(o); ret doubleValue; }
46  
      else if (o cast Class) {
47  
        m.classConstant(o);
48  
        ret objValue;
49  
      } else if (o cast Bool) {
50  
        m.boolConstant(o);
51  
        ret intValue;
52  
      } else
53  
        fail("Can't compile const value: " + toStringWithClass(o));
54  
    } else if (code cast Tb.Script) {
55  
      var stackTop = none;
56  
      for (step : code.steps) {
57  
        // pop result of last instruction if any
58  
        if (stackTop != none)
59  
          m.add(new POP);
60  
          
61  
        stackTop = compile(step);
62  
      }
63  
      ret stackTop;
64  
    } else if (code cast Tb.CallMethod) {
65  
      // push target
66  
      compileToObject(code.target);
67  
      
68  
      // push method name
69  
      m.stringConstant(code.methodName);
70  
      
71  
      // push argument array
72  
      argumentsAsArray(code.args);
73  
      
74  
      // call call()
75  
      m.invokeStatic(mainFunctionHolder call, O, "call", O, S, O[].class);
76  
      ret objValue;
77  
    } else if (code cast Tb.CallMethodOrGetField) {
78  
      // push target
79  
      compileToObject(code.target);
80  
      
81  
      // push method/field name
82  
      m.stringConstant(code.name);
83  
      
84  
      // call call()
85  
      m.invokeStatic(mainFunctionHolder call, O, "preciseGetOrCallMethod", O, S);
86  
      ret objValue;
87  
    } else if (code cast Tb.SetField) {
88  
      // push target
89  
      compileToObject(code.target);
90  
      
91  
      // push field name
92  
      m.stringConstant(code.name);
93  
      
94  
      // push value
95  
      compileToObject(code.expr);
96  
      
97  
      // call set()
98  
      m.invokeStatic(mainFunctionHolder set, O, "set", O, S, O);
99  
      ret none;
100  
    } else if (code cast Tb.NewObject) {
101  
      // push class
102  
      m.classConstant(code.c);
103  
      
104  
      argumentsAsArray(code.args);
105  
      
106  
      // call nuObject()
107  
      m.invokeStatic(mainFunctionHolder nuObject, O, "nuObject", Class.class, O[].class);
108  
      ret objValue;
109  
    } else if (code cast Tb.Assignment) {
110  
      // evaluate expression, store in temporary variable
111  
      compileToObject(code.expression);
112  
      m.astore(iTemp());
113  
      
114  
      // Call VarContext.set()
115  
      loadVarContext();
116  
      m.stringConstant(code.var);
117  
      m.aload(iTemp());
118  
      m.invokeVirtual(VarContext, void.class, "set", S, O);
119  
      
120  
      m.aload(iTemp());
121  
      ret objValue;
122  
    } else if (code cast Tb.While) {
123  
    
124  
    /* Simulating this:
125  
      
126  
       while (ping() && (Bool) condition.get(ctx)) {
127  
         body.get(ctx);
128  
       }
129  
       null;
130  
    */
131  
    
132  
      // Mark loop start as jump target
133  
      var loopStart = m.il.append(new NOP);
134  
135  
      // Call ping() unless disabled
136  
      BranchInstruction branch1 = null;
137  
      if (callPing) {
138  
        m.invokeStatic(mainFunctionHolder ping, bool.class, "ping");
139  
        branch1 = new IFEQ(null);
140  
        m.add(branch1);
141  
      }
142  
      
143  
      // Evaluate condition
144  
      compileToBool(code.condition);
145  
      var branch2 = new IFEQ(null);
146  
      m.add(branch2);
147  
      
148  
      // Evaluate body
149  
      discardStackTop(compile(code.body));
150  
      
151  
      // Jump to loop start
152  
      m.add(new GOTO(loopStart));
153  
      
154  
      // Update forward branches
155  
      var loopEnd = m.il.append(new NOP);
156  
      branch1?.setTarget(loopEnd);
157  
      branch2.setTarget(loopEnd);
158  
      
159  
      ret none;
160  
    } else if (code cast Tb.IfThen) {
161  
      compileToBool(code.condition);
162  
      var branch1 = new IFEQ(null);
163  
      m.add(branch1);
164  
      
165  
      // Evaluate body
166  
      var stackTop = compile(code.body);
167  
      
168  
      // body returns nothing? then we don't need an else branch
169  
      if (stackTop == none) {
170  
        branch1.setTarget(here());
171  
        ret stackTop;
172  
      } else {
173  
        // otherwise, convert to object and return null in else branch
174  
        convertToObject(stackTop);
175  
        var jumpToEnd = m.forwardGoto();
176  
        branch1.setTarget(here());
177  
        loadNull();
178  
        jumpToEnd.setTarget(m.here());
179  
        ret objValue;
180  
      }
181  
    } else if (code cast Tb.GetVar) {
182  
      ret compileGetVar(code);
183  
    } else if (code cast Tb.ReturnFromScript) {
184  
      if (code.script != returnableScript)
185  
        fail("Can only return from current script");
186  
        
187  
      var stackTop = compile(code.value);
188  
      if (postConversion != null)
189  
        stackTop = postConversion.get(stackTop);
190  
      m.returnWithType(stackTop);
191  
      ret none;
192  
    }
193  
    
194  
    fail("Can't compile yet: " + className(code));
195  
  }
196  
197  
  void argumentsAsArray(Evaluable[] args) {  
198  
    int n = l(args);
199  
    m.intConst(n);
200  
    m.add(new ANEWARRAY(m.classRef(O)));
201  
    for iArg to n: {
202  
      m.dup(); // get array again
203  
      m.intConst(iArg);
204  
      compileToObject(args[iArg]);
205  
      m.add(new AASTORE);
206  
    }
207  
  }
208  
  
209  
  void loadVarContext {
210  
    assertTrue("Need VarContext", iVarContext >= 0);
211  
    m.aload(iVarContext);
212  
  }
213  
  
214  
  // index of a temporary variable, created on demand
215  
  simplyCached int iTemp() {
216  
    ret m.newLocalVar();
217  
  }
218  
  
219  
  void compileToBool(Evaluable condition) {
220  
    var stackTop = compile(condition);
221  
    if (stackTop == objValue) {
222  
      // cast to Boolean
223  
      m.checkCast(Bool.class);
224  
      
225  
      // call Boolean.booleanValue()
226  
      m.invokeVirtual(Bool.class, bool.class, "booleanValue");
227  
    } else if (stackTop == intValue) {} // ok
228  
    else fail("Can't convert to bool: " + stackTop);
229  
  }
230  
231  
  JVMStackCellType compileGetVar(Tb.GetVar code) {
232  
    // Prepare VarContext.get()
233  
    loadVarContext();
234  
    m.stringConstant(code.var);
235  
    
236  
    // call VarContext.get()
237  
    m.invokeVirtual(VarContext, O, "get", S);
238  
    ret objValue;
239  
  }
240  
}

download  show line numbers  debug dex  old transpilations   

Travelled to 4 computer(s): bhatertpkbcr, ekrmjmnbrukm, mowyntqkapby, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1034318
Snippet name: LASToByteCode [works for many language constructs already!]
Eternal ID of this version: #1034318/60
Text MD5: 45a3c6205c10b2da44e97aff01b3db9a
Transpilation MD5: b3cc75795f4f4ba4052728b91b2b6b06
Author: stefan
Category: javax / left arrow script
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-04-02 17:23:10
Source code size: 6955 bytes / 240 lines
Pitched / IR pitched: No / No
Views / Downloads: 249 / 604
Version history: 59 change(s)
Referenced in: [show references]