├── .gitignore ├── build.gradle ├── settings.gradle └── src ├── main ├── java │ └── org │ │ └── railgun │ │ ├── Controls.java │ │ ├── FileManager.java │ │ ├── RailGun.java │ │ ├── Timer.java │ │ ├── action │ │ ├── ActionController.java │ │ ├── CloseHandler.java │ │ ├── CompileHandler.java │ │ ├── ExitHandler.java │ │ ├── KeyPressedHandler.java │ │ ├── MouseDragEnterHandler.java │ │ ├── MouseDragHandler.java │ │ ├── MouseDragReleaseHandler.java │ │ ├── MouseLeftClickedHandler.java │ │ ├── NewFileHandler.java │ │ ├── OpenBinaryHandler.java │ │ ├── OpenFileHandler.java │ │ ├── RunHandler.java │ │ ├── SaveHandler.java │ │ └── TextChangedHandler.java │ │ ├── canvas │ │ └── View.java │ │ ├── marshal │ │ ├── BinaryFileParser.java │ │ └── CodeObject.java │ │ ├── shape │ │ ├── AbstractShape.java │ │ ├── Arrow.java │ │ ├── Circle.java │ │ ├── RGLine.java │ │ ├── RGRoundRect.java │ │ ├── RGText.java │ │ ├── Rect.java │ │ ├── Shape.java │ │ └── Star.java │ │ └── vm │ │ ├── Bytecode.java │ │ ├── Interpreter.java │ │ ├── intrisinc │ │ ├── AddTimerMethod.java │ │ ├── CameraMethod.java │ │ ├── CircleMethod.java │ │ ├── FrameCountMethod.java │ │ ├── InnerMethod.java │ │ ├── KeyMapMethod.java │ │ ├── LenMethod.java │ │ ├── MouseMapMethod.java │ │ ├── RGLineMethod.java │ │ ├── RGRectMethod.java │ │ ├── RGRoundRectMethod.java │ │ ├── RGTextMethod.java │ │ ├── RandomMethod.java │ │ ├── RgbMethod.java │ │ ├── StarMethod.java │ │ └── UpdateFunctionMethod.java │ │ ├── object │ │ ├── AbstractBuiltinMethodObject.java │ │ ├── BuiltinMethodObject.java │ │ ├── Klass.java │ │ ├── ListKlass.java │ │ ├── NoneObject.java │ │ ├── RGFrameObject.java │ │ ├── RGFunctionObject.java │ │ ├── RGMethodObject.java │ │ └── RGObject.java │ │ └── time │ │ ├── UserTimer.java │ │ ├── UserTimerKlass.java │ │ └── UserTimerManager.java └── python │ └── rgparser │ ├── README.md │ ├── ast2pyc.py │ ├── check_ast.py │ ├── compile.bat │ ├── ddl.py │ ├── ddlib │ ├── __init__.py │ ├── assem.py │ ├── ddlex.py │ └── ddyacc.py │ ├── dsparserlib │ ├── __init__.py │ ├── lex.py │ └── pylex.py │ ├── env.cmd │ ├── py_src │ ├── Grammar │ └── tokenizer.c │ ├── pyparser.py │ ├── rg │ ├── drawCircle.rg │ ├── drawFlag.rg │ ├── drawText.rg │ ├── easySnake.rg │ ├── eight_number.rg │ ├── lambda.rg │ ├── renju.rg │ ├── snake.rg │ ├── test3d.rg │ ├── testClass.rg │ └── testMouse.rg │ ├── show.py │ ├── symtable │ ├── Assem.py │ ├── CodeGen.py │ ├── Scope.py │ ├── SymtableVisitor.py │ ├── const.py │ ├── testfiles │ │ ├── test_assign_print.ldd │ │ ├── test_class.ldd │ │ ├── test_comp.ldd │ │ ├── test_control.ldd │ │ ├── test_datas.ldd │ │ ├── test_func.ldd │ │ ├── test_if.ldd │ │ ├── test_stmt.ldd │ │ ├── test_subscr.ldd │ │ ├── test_try.ldd │ │ └── test_with.ldd │ └── unit_test.py │ └── test │ ├── test.ddl │ ├── test.hy │ ├── test.py │ ├── test.rgb │ ├── test_class.ddl │ ├── test_dict.ddl │ ├── test_for.ddl │ ├── test_func.ddl │ ├── test_if.ddl │ ├── test_import.ddl │ ├── test_list.ddl │ ├── test_print.ddl │ ├── test_try.ddl │ └── test_while.ddl └── test ├── java └── LibraryTest.java ├── python ├── drawCircle.py ├── drawText.py └── eight_number.py └── rg └── drawFlag.rg /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.rgb 3 | *.pyc 4 | *.out 5 | 6 | 7 | */.idea/* 8 | 9 | output/* 10 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This build file was auto generated by running the Gradle 'init' task 3 | * by 'hinus' at '17-11-30 下午4:13' with Gradle 3.2.1 4 | * 5 | * This generated file contains a sample Java project to get you started. 6 | * For more details take a look at the Java Quickstart chapter in the Gradle 7 | * user guide available at https://docs.gradle.org/3.2.1/userguide/tutorial_java_projects.html 8 | */ 9 | 10 | // Apply the java plugin to add support for Java 11 | apply plugin: 'java' 12 | 13 | // In this section you declare where to find the dependencies of your project 14 | repositories { 15 | // Use 'jcenter' for resolving your dependencies. 16 | // You can declare any Maven/Ivy/file repository here. 17 | jcenter() 18 | } 19 | 20 | // In this section you declare the dependencies for your production and test code 21 | dependencies { 22 | // The production code uses the SLF4J logging API at compile time 23 | compile 'org.slf4j:slf4j-api:1.7.21' 24 | 25 | // Declare the dependency for your favourite test framework you want to use in your tests. 26 | // TestNG is also supported by the Gradle Test task. Just change the 27 | // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add 28 | // 'test.useTestNG()' to your build script. 29 | testCompile 'junit:junit:4.12' 30 | } 31 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This settings file was auto generated by the Gradle buildInit task 3 | * by 'hinus' at '17-11-30 下午4:13' with Gradle 3.2.1 4 | * 5 | * The settings file is used to specify which projects to include in your build. 6 | * In a single project build this file can be empty or even removed. 7 | * 8 | * Detailed information about configuring a multi-project build in Gradle can be found 9 | * in the user guide at https://docs.gradle.org/3.2.1/userguide/multi_project_builds.html 10 | */ 11 | 12 | /* 13 | // To declare projects as part of a multi-project build use the 'include' method 14 | include 'shared' 15 | include 'api' 16 | include 'services:webservice' 17 | */ 18 | 19 | rootProject.name = 'railgun' 20 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/Controls.java: -------------------------------------------------------------------------------- 1 | package org.railgun; 2 | 3 | import javafx.scene.Camera; 4 | import javafx.scene.Group; 5 | import javafx.scene.SubScene; 6 | import javafx.scene.canvas.Canvas; 7 | import javafx.scene.control.TextArea; 8 | import javafx.scene.layout.BorderPane; 9 | import javafx.stage.Stage; 10 | 11 | /** 12 | * Created by hinus on 2017/11/30. 13 | */ 14 | public class Controls { 15 | private static Controls instance = new Controls(); 16 | 17 | private TextArea sourceCode; 18 | private Stage mainStage; 19 | private BorderPane mainPane; 20 | 21 | private Group graph3d; 22 | private Camera camera; 23 | 24 | public Camera getCamera() { 25 | return camera; 26 | } 27 | 28 | public void setCamera(Camera camera) { 29 | this.camera = camera; 30 | } 31 | 32 | private Timer timer; 33 | 34 | public Timer getTimer() { 35 | return timer; 36 | } 37 | 38 | public void setTimer(Timer timer) { 39 | this.timer = timer; 40 | } 41 | 42 | public void closeTimer() { 43 | if (this.timer != null) { 44 | this.timer.exit(); 45 | this.timer = null; 46 | } 47 | } 48 | 49 | public BorderPane getMainPane() { 50 | return mainPane; 51 | } 52 | 53 | public void setMainPane(BorderPane mainPane) { 54 | this.mainPane = mainPane; 55 | } 56 | 57 | private Canvas canvas; 58 | 59 | public static Controls getInstance() { 60 | return instance; 61 | } 62 | 63 | public TextArea getSourceCode() { 64 | 65 | return sourceCode; 66 | } 67 | 68 | public void setSourceCode(TextArea sourceCode) { 69 | this.sourceCode = sourceCode; 70 | } 71 | 72 | public Stage getMainStage() { 73 | return mainStage; 74 | } 75 | 76 | public void setMainStage(Stage mainStage) { 77 | this.mainStage = mainStage; 78 | } 79 | 80 | public Canvas getCanvas() { 81 | return canvas; 82 | } 83 | 84 | public void setCanvas(Canvas canvas) { 85 | this.canvas = canvas; 86 | } 87 | 88 | private Controls() { 89 | } 90 | 91 | public Group getGraph3d() { 92 | return graph3d; 93 | } 94 | 95 | public void setGraph3d(Group graph3d) { 96 | this.graph3d = graph3d; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/FileManager.java: -------------------------------------------------------------------------------- 1 | package org.railgun; 2 | 3 | import javafx.scene.control.ButtonType; 4 | import javafx.scene.control.Dialog; 5 | import javafx.stage.FileChooser; 6 | 7 | import java.io.*; 8 | import java.util.Optional; 9 | 10 | /** 11 | * Created by hinus on 2017/11/30. 12 | */ 13 | public class FileManager { 14 | private static FileManager instance = new FileManager(); 15 | 16 | private String sourceFileName; 17 | private String binaryFileName; 18 | 19 | private boolean isDirty; 20 | 21 | public boolean isDirty() { 22 | return isDirty; 23 | } 24 | 25 | public void setDirty(boolean dirty) { 26 | isDirty = dirty; 27 | } 28 | 29 | private byte[] binaryContent; 30 | 31 | private FileManager() { 32 | } 33 | 34 | public static FileManager getInstance() { 35 | return instance; 36 | } 37 | 38 | public String getSourceFileName() { 39 | return sourceFileName; 40 | } 41 | 42 | public void setSourceFileName(String sourceFileName) { 43 | this.sourceFileName = sourceFileName; 44 | } 45 | 46 | public String getBinaryFileName() { 47 | return binaryFileName; 48 | } 49 | 50 | public byte[] getBinaryContent() { 51 | return binaryContent; 52 | } 53 | 54 | public void setBinaryContent(byte[] binaryContent) { 55 | this.binaryContent = binaryContent; 56 | } 57 | 58 | public void setBinaryFileName(String binaryFileName) { 59 | this.binaryFileName = binaryFileName; 60 | } 61 | 62 | public void clear() { 63 | this.sourceFileName = null; 64 | 65 | this.binaryContent = null; 66 | this.binaryFileName = null; 67 | } 68 | 69 | /** 70 | * 71 | * @return true, if save file successfully. 72 | */ 73 | public boolean saveCurrentFile() { 74 | if (!isDirty) 75 | return true; 76 | 77 | String s = Controls.getInstance().getSourceCode().getText(); 78 | 79 | if (sourceFileName != null && !sourceFileName.equals("")) { 80 | FileOutputStream fos = null; 81 | 82 | try { 83 | fos = new FileOutputStream(sourceFileName, false); 84 | fos.write(s.getBytes()); 85 | fos.flush(); 86 | fos.close(); 87 | } catch (IOException e) { 88 | e.printStackTrace(); 89 | } finally { 90 | } 91 | } 92 | else { 93 | FileChooser fileChooser = new FileChooser(); 94 | fileChooser.setTitle("Save RailGun File"); 95 | fileChooser.getExtensionFilters().addAll( 96 | new FileChooser.ExtensionFilter("railgun file", "*.rg")); 97 | 98 | File selectedFile = fileChooser.showSaveDialog(Controls.getInstance().getMainStage()); 99 | 100 | if (selectedFile == null) 101 | return false; 102 | 103 | try { 104 | FileOutputStream fos = new FileOutputStream(selectedFile); 105 | fos.write(s.getBytes()); 106 | fos.flush(); 107 | fos.close(); 108 | } catch (FileNotFoundException e) { 109 | e.printStackTrace(); 110 | } catch (IOException e) { 111 | e.printStackTrace(); 112 | } 113 | } 114 | 115 | isDirty = false; 116 | return true; 117 | } 118 | 119 | /** 120 | * 121 | * @return shouldContinue. If dirty file is saved, continue; if user choose to not save, 122 | * continue; else, abort. 123 | */ 124 | public boolean tryToSaveDirtyFile() { 125 | Dialog dialog = new Dialog<>(); 126 | dialog.setHeaderText("Warning!"); 127 | dialog.setContentText("File has not been saved, do you want to save it?"); 128 | dialog.getDialogPane().getButtonTypes().addAll(ButtonType.YES, ButtonType.NO, ButtonType.CANCEL); 129 | Optional result = dialog.showAndWait(); 130 | 131 | if (!result.isPresent()) 132 | return false; 133 | 134 | if (result.get() == ButtonType.NO) { 135 | return true; 136 | } 137 | else if (result.get() == ButtonType.YES) { 138 | return FileManager.getInstance().saveCurrentFile(); 139 | } 140 | else if (result.get() == ButtonType.CANCEL) { 141 | return false; 142 | } 143 | else 144 | return false; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/RailGun.java: -------------------------------------------------------------------------------- 1 | package org.railgun; 2 | 3 | import com.sun.org.apache.xpath.internal.operations.Mod; 4 | import javafx.application.Application; 5 | import javafx.scene.Group; 6 | import javafx.scene.PerspectiveCamera; 7 | import javafx.scene.Scene; 8 | import javafx.scene.SubScene; 9 | import javafx.scene.canvas.Canvas; 10 | import javafx.scene.control.*; 11 | import javafx.scene.layout.BorderPane; 12 | import javafx.scene.paint.Color; 13 | import javafx.scene.paint.PhongMaterial; 14 | import javafx.scene.shape.Box; 15 | import javafx.scene.shape.DrawMode; 16 | import javafx.scene.transform.Rotate; 17 | import javafx.scene.transform.Translate; 18 | import javafx.stage.Stage; 19 | import org.railgun.action.*; 20 | //import org.railgun.animation.TransitionController; 21 | import org.railgun.marshal.BinaryFileParser; 22 | import org.railgun.shape.Circle; 23 | import org.railgun.shape.Rect; 24 | import org.railgun.shape.Star; 25 | 26 | import java.io.File; 27 | import java.io.FileInputStream; 28 | import java.io.IOException; 29 | 30 | 31 | /** 32 | * Created by hinus on 2017/11/30. 33 | */ 34 | public class RailGun extends Application { 35 | public static void main(String[] args) { 36 | launch(args); 37 | } 38 | 39 | @Override 40 | public void start(Stage primaryStage) { 41 | Controls controlsManager = Controls.getInstance(); 42 | controlsManager.setMainStage(primaryStage); 43 | 44 | // initialize canvas 45 | BorderPane mainPane = new BorderPane(); 46 | boolean is2d = true; 47 | Scene scene = null; 48 | 49 | if (is2d) { 50 | Canvas canvas = new Canvas(1000, 600); 51 | mainPane.setCenter(canvas); 52 | Controls.getInstance().setCanvas(canvas); 53 | 54 | scene = new Scene(mainPane, 1000, 750); 55 | } 56 | else { 57 | // test 3d 58 | Box testBox = new Box(5, 5, 5); 59 | testBox.setMaterial(new PhongMaterial(Color.BROWN)); 60 | testBox.setDrawMode(DrawMode.FILL); 61 | 62 | Group root = new Group(); 63 | root.getChildren().add(testBox); 64 | 65 | SubScene subScene = new SubScene(root, 1000, 600); 66 | Controls.getInstance().setGraph3d(root); 67 | 68 | mainPane.setCenter(subScene); 69 | 70 | scene = new Scene(mainPane, 1000, 750); 71 | } 72 | 73 | scene.setOnKeyPressed(new KeyPressedHandler()); 74 | controlsManager.setMainPane(mainPane); 75 | 76 | createMenu(mainPane, primaryStage); 77 | 78 | TextArea sourceCode = new TextArea(""); 79 | sourceCode.setDisable(true); 80 | mainPane.setBottom(sourceCode); 81 | controlsManager.setSourceCode(sourceCode); 82 | sourceCode.textProperty().addListener(new TextChangedHandler()); 83 | 84 | /* 85 | initPropertyPanel(mainPane); 86 | initMVC(canvas); 87 | initSceneAction(scene); 88 | initCanvasAction(canvas); 89 | 90 | canvas.setOnKeyTyped(new PaintToolAction()); 91 | 92 | */ 93 | primaryStage.setTitle("RailGun"); 94 | primaryStage.setScene(scene); 95 | primaryStage.show(); 96 | 97 | // some test case 98 | /* 99 | /// Chinese flag 100 | Star s = Star.makeStar(200, 200, 60); 101 | Star s2 = Star.makeStar(300, 140, 20); 102 | s2.rotate(-0.8771); 103 | Star s3 = Star.makeStar(340, 180, 20); 104 | s3.rotate(-0.4786); 105 | Star s4 = Star.makeStar(340, 240, 20); 106 | s4.rotate(0.0584); 107 | Star s5 = Star.makeStar(300, 280, 20); 108 | s5.rotate(0.3381); 109 | */ 110 | 111 | 112 | /* 113 | Rect redRect = Rect.makeRect(100, 100, 180, 400, true, Color.rgb(239, 65, 53)); 114 | Rect whiteRect = Rect.makeRect(280, 100, 198, 400, true, Color.WHITE); 115 | Rect blueRect = Rect.makeRect(478, 100, 222, 400, true, Color.rgb(0, 85, 164));*/ 116 | 117 | 118 | /* 119 | try { 120 | File f = new File("C:/test.pyc"); 121 | FileInputStream fis = new FileInputStream(f); 122 | byte[] buf = new byte[10 * 1024]; 123 | fis.read(buf); 124 | BinaryFileParser.parse(buf); 125 | } catch (IOException e) { 126 | e.printStackTrace(); 127 | }*/ 128 | 129 | /* 130 | Circle c = Circle.makeCircle(200, 200, 60, 60, true); 131 | c.setMoveController(new TransitionController(c, 400, 0, 500, 0, true)); 132 | */ 133 | } 134 | 135 | public void createMenu(BorderPane mainPane, Stage mainStage) { 136 | MenuBar menuBar = new MenuBar(); 137 | Menu menuFile = new Menu("File"); 138 | 139 | MenuItem openFile = new MenuItem("Open"); 140 | MenuItem newFile = new MenuItem("New"); 141 | MenuItem saveFile = new MenuItem("Save"); 142 | MenuItem closeFile = new MenuItem("Close"); 143 | MenuItem exitMain = new MenuItem("Exit"); 144 | 145 | MenuItem openBinary = new MenuItem("Open Binary"); 146 | 147 | menuFile.getItems().addAll(openFile, newFile, saveFile, closeFile, new SeparatorMenuItem(), openBinary, new SeparatorMenuItem(), exitMain); 148 | 149 | Menu menuRun = new Menu("Run"); 150 | 151 | MenuItem compileRG = new MenuItem("Compile"); 152 | MenuItem runRG = new MenuItem("Run"); 153 | 154 | menuRun.getItems().addAll(compileRG, runRG); 155 | 156 | menuBar.getMenus().addAll(menuFile, menuRun); 157 | 158 | // set actions 159 | openFile.setOnAction(new OpenFileHandler()); 160 | newFile.setOnAction(new NewFileHandler()); 161 | saveFile.setOnAction(new SaveHandler()); 162 | closeFile.setOnAction(new CloseHandler()); 163 | 164 | openBinary.setOnAction(new OpenBinaryHandler()); 165 | 166 | exitMain.setOnAction(new ExitHandler()); 167 | 168 | compileRG.setOnAction(new CompileHandler()); 169 | runRG.setOnAction(new RunHandler()); 170 | 171 | mainPane.setTop(menuBar); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/Timer.java: -------------------------------------------------------------------------------- 1 | package org.railgun; 2 | 3 | import org.railgun.action.ActionController; 4 | import org.railgun.canvas.View; 5 | import org.railgun.vm.Interpreter; 6 | import org.railgun.vm.object.RGFunctionObject; 7 | import org.railgun.vm.time.UserTimerManager; 8 | 9 | /** 10 | * Created by hinus on 2017/12/1. 11 | */ 12 | public class Timer extends Thread { 13 | volatile boolean hasDone = false; 14 | 15 | static int framesPerSecond = 40; 16 | static long frameDuration = 1000 / framesPerSecond; 17 | 18 | public static volatile long frameCnt = 0; 19 | 20 | public static void setFramesPerSecond(int framesPerSecond) { 21 | if (framesPerSecond <= 0 || framesPerSecond > 60) 22 | return; 23 | 24 | Timer.framesPerSecond = framesPerSecond; 25 | frameDuration = 1000 / framesPerSecond; 26 | } 27 | 28 | @Override 29 | public void run() { 30 | while (!hasDone) { 31 | frameCnt += 1; 32 | long begin = System.currentTimeMillis(); 33 | RGFunctionObject fo = ActionController.getActionController().getUpdateFunction(); 34 | 35 | if (fo != null) { 36 | View.getView().clear(); 37 | Interpreter.getInstance().run(fo); 38 | } 39 | 40 | UserTimerManager.getManager().refresh(frameCnt); 41 | 42 | long duration = System.currentTimeMillis() - begin; 43 | 44 | // make sure only 50 frames per second 45 | if (duration < frameDuration) { 46 | try { 47 | Thread.sleep(frameDuration - duration); 48 | } catch (InterruptedException e) { 49 | } 50 | } 51 | } 52 | } 53 | 54 | public void exit() { 55 | hasDone = true; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/action/ActionController.java: -------------------------------------------------------------------------------- 1 | package org.railgun.action; 2 | 3 | import org.railgun.vm.object.RGFunctionObject; 4 | 5 | import java.util.HashMap; 6 | 7 | /** 8 | * Created by hinus on 2017/12/2. 9 | */ 10 | public class ActionController { 11 | private static ActionController actionController = new ActionController(); 12 | 13 | private HashMap keyMap = new HashMap<>(); 14 | 15 | private HashMap mouseMap = new HashMap(); 16 | 17 | private volatile RGFunctionObject updateFunction; 18 | 19 | public RGFunctionObject getUpdateFunction() { 20 | return updateFunction; 21 | } 22 | 23 | public void setUpdateFunction(RGFunctionObject updateFunction) { 24 | this.updateFunction = updateFunction; 25 | } 26 | 27 | public ActionController() { 28 | } 29 | 30 | public HashMap getKeyMap() { 31 | return keyMap; 32 | } 33 | 34 | public void setKeyMap(HashMap keyMap) { 35 | this.keyMap = keyMap; 36 | } 37 | 38 | public static ActionController getActionController() { 39 | return actionController; 40 | } 41 | 42 | public HashMap getMouseMap() { 43 | return mouseMap; 44 | } 45 | 46 | public void setMouseMap(HashMap mouseMap) { 47 | this.mouseMap = mouseMap; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/action/CloseHandler.java: -------------------------------------------------------------------------------- 1 | package org.railgun.action; 2 | 3 | import javafx.event.ActionEvent; 4 | import javafx.event.EventHandler; 5 | import org.railgun.Controls; 6 | import org.railgun.FileManager; 7 | 8 | /** 9 | * Created by hinus on 2017/11/30. 10 | */ 11 | public class CloseHandler implements EventHandler { 12 | @Override 13 | public void handle(ActionEvent event) { 14 | FileManager fileManager = FileManager.getInstance(); 15 | // if file is not saved, let user confirm it. 16 | if (fileManager.isDirty()) { 17 | if (!fileManager.tryToSaveDirtyFile()) { 18 | return; 19 | } 20 | } 21 | 22 | Controls controls = Controls.getInstance(); 23 | controls.getSourceCode().setDisable(true); 24 | controls.getSourceCode().clear(); 25 | controls.closeTimer(); 26 | 27 | fileManager.clear(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/action/CompileHandler.java: -------------------------------------------------------------------------------- 1 | package org.railgun.action; 2 | 3 | import javafx.event.ActionEvent; 4 | import javafx.event.EventHandler; 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.FileNotFoundException; 8 | import java.io.IOException; 9 | 10 | import org.railgun.FileManager; 11 | 12 | /** 13 | * Created by hinus on 2017/11/30. 14 | */ 15 | public class CompileHandler implements EventHandler { 16 | @Override 17 | public void handle(ActionEvent event) { 18 | FileManager fileManager = FileManager.getInstance(); 19 | String sourceFileName = fileManager.getSourceFileName(); 20 | if (sourceFileName != null) { 21 | try { 22 | String windowsCmd = "cmd /c \"cd .\\main\\python\\rgparser && python ddl.py " + fileManager.getSourceFileName() +" > nul\""; 23 | Process p = Runtime.getRuntime().exec(windowsCmd); 24 | 25 | p.waitFor(); 26 | } catch (IOException e) { 27 | e.printStackTrace(); 28 | } catch (InterruptedException e) { 29 | // TODO: Need to process exitVal != 0; 30 | e.printStackTrace(); 31 | } 32 | 33 | String binaryFileName = sourceFileName + "b"; 34 | 35 | File binaryFile = new File(binaryFileName); 36 | if (binaryFile == null || !binaryFile.exists()) { 37 | return; 38 | } 39 | 40 | fileManager.setBinaryFileName(binaryFileName); 41 | 42 | byte[] sourceContent = new byte[(int) binaryFile.length()]; 43 | 44 | try { 45 | FileInputStream fileInputStream = new FileInputStream(binaryFile); 46 | fileInputStream.read(sourceContent); 47 | fileManager.setBinaryContent(sourceContent); 48 | 49 | fileInputStream.close(); 50 | } catch (FileNotFoundException e) { 51 | e.printStackTrace(); 52 | } catch (IOException e) { 53 | e.printStackTrace(); 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/action/ExitHandler.java: -------------------------------------------------------------------------------- 1 | package org.railgun.action; 2 | 3 | import javafx.event.ActionEvent; 4 | import javafx.event.EventHandler; 5 | 6 | /** 7 | * Created by hinus on 2017/11/30. 8 | */ 9 | public class ExitHandler implements EventHandler { 10 | @Override 11 | public void handle(ActionEvent event) { 12 | System.exit(0); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/action/KeyPressedHandler.java: -------------------------------------------------------------------------------- 1 | package org.railgun.action; 2 | 3 | import javafx.event.EventHandler; 4 | import javafx.scene.input.KeyEvent; 5 | import org.railgun.vm.Interpreter; 6 | import org.railgun.vm.object.RGFunctionObject; 7 | 8 | /** 9 | * Created by hinus on 2017/12/2. 10 | */ 11 | public class KeyPressedHandler implements EventHandler { 12 | @Override 13 | public void handle(KeyEvent event) { 14 | RGFunctionObject fo = null; 15 | switch (event.getCode()) { 16 | case UP: 17 | fo = (RGFunctionObject) ActionController.getActionController().getKeyMap().get("VK_UP"); 18 | break; 19 | case DOWN: 20 | fo = (RGFunctionObject) ActionController.getActionController().getKeyMap().get("VK_DOWN"); 21 | break; 22 | case LEFT: 23 | fo = (RGFunctionObject) ActionController.getActionController().getKeyMap().get("VK_LEFT"); 24 | break; 25 | case RIGHT: 26 | fo = (RGFunctionObject) ActionController.getActionController().getKeyMap().get("VK_RIGHT"); 27 | break; 28 | case SPACE: 29 | fo = (RGFunctionObject) ActionController.getActionController().getKeyMap().get("VK_SPACE"); 30 | break; 31 | } 32 | 33 | if (fo != null) 34 | Interpreter.getInstance().run(fo); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/action/MouseDragEnterHandler.java: -------------------------------------------------------------------------------- 1 | package org.railgun.action; 2 | 3 | import javafx.event.EventHandler; 4 | import javafx.scene.input.MouseEvent; 5 | 6 | /** 7 | * Created by hinus on 2017/12/5. 8 | */ 9 | public class MouseDragEnterHandler implements EventHandler { 10 | @Override 11 | public void handle(MouseEvent event) { 12 | System.out.println("drag begin"); 13 | event.consume(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/action/MouseDragHandler.java: -------------------------------------------------------------------------------- 1 | package org.railgun.action; 2 | 3 | import javafx.event.EventHandler; 4 | import javafx.scene.input.MouseEvent; 5 | import org.railgun.vm.Interpreter; 6 | import org.railgun.vm.object.RGFunctionObject; 7 | 8 | import java.util.HashMap; 9 | 10 | /** 11 | * Created by hinus on 2017/12/5. 12 | */ 13 | public class MouseDragHandler implements EventHandler { 14 | @Override 15 | public void handle(MouseEvent event) { 16 | HashMap mouseMap = ActionController.getActionController().getMouseMap(); 17 | 18 | if (mouseMap == null || mouseMap.isEmpty()) 19 | return; 20 | 21 | RGFunctionObject fo = (RGFunctionObject)mouseMap.get("DRAG"); 22 | 23 | if (fo == null) 24 | return; 25 | 26 | Interpreter.getInstance().run(fo, Integer.valueOf((int)event.getX()), Integer.valueOf((int)event.getY())); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/action/MouseDragReleaseHandler.java: -------------------------------------------------------------------------------- 1 | package org.railgun.action; 2 | 3 | import javafx.event.EventHandler; 4 | import javafx.scene.input.MouseEvent; 5 | 6 | /** 7 | * Created by hinus on 2017/12/5. 8 | */ 9 | public class MouseDragReleaseHandler implements EventHandler { 10 | @Override 11 | public void handle(MouseEvent event) { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/action/MouseLeftClickedHandler.java: -------------------------------------------------------------------------------- 1 | package org.railgun.action; 2 | 3 | import javafx.event.EventHandler; 4 | import javafx.scene.input.MouseEvent; 5 | import org.railgun.vm.Interpreter; 6 | import org.railgun.vm.object.RGFunctionObject; 7 | 8 | import java.util.HashMap; 9 | 10 | /** 11 | * Created by hinus on 2017/12/4. 12 | */ 13 | public class MouseLeftClickedHandler implements EventHandler { 14 | @Override 15 | public void handle(MouseEvent event) { 16 | HashMap mouseMap = ActionController.getActionController().getMouseMap(); 17 | 18 | if (mouseMap == null || mouseMap.isEmpty()) 19 | return; 20 | 21 | RGFunctionObject fo = (RGFunctionObject)mouseMap.get("LEFT_CLICK"); 22 | 23 | if (fo == null) 24 | return; 25 | 26 | Interpreter.getInstance().run(fo, Integer.valueOf((int)event.getX()), Integer.valueOf((int)event.getY())); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/action/NewFileHandler.java: -------------------------------------------------------------------------------- 1 | package org.railgun.action; 2 | 3 | import javafx.event.ActionEvent; 4 | import javafx.event.EventHandler; 5 | import org.railgun.Controls; 6 | import org.railgun.FileManager; 7 | 8 | /** 9 | * Created by hinus on 2017/11/30. 10 | */ 11 | public class NewFileHandler implements EventHandler { 12 | @Override 13 | public void handle(ActionEvent event) { 14 | FileManager fileManager = FileManager.getInstance(); 15 | 16 | if (fileManager.isDirty()) { 17 | if (!fileManager.tryToSaveDirtyFile()) { 18 | return; 19 | } 20 | } 21 | 22 | Controls controls = Controls.getInstance(); 23 | controls.getSourceCode().setDisable(false); 24 | controls.getSourceCode().clear(); 25 | controls.closeTimer(); 26 | 27 | FileManager.getInstance().clear(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/action/OpenBinaryHandler.java: -------------------------------------------------------------------------------- 1 | package org.railgun.action; 2 | 3 | import javafx.event.ActionEvent; 4 | import javafx.event.EventHandler; 5 | import javafx.scene.control.TextArea; 6 | import javafx.stage.FileChooser; 7 | import javafx.stage.Stage; 8 | import org.railgun.Controls; 9 | import org.railgun.FileManager; 10 | 11 | import java.io.*; 12 | 13 | /** 14 | * Created by hinus on 2017/12/1. 15 | */ 16 | public class OpenBinaryHandler implements EventHandler { 17 | private File initialDirectory = null; 18 | 19 | @Override 20 | public void handle(ActionEvent event) { 21 | Stage mainStage = Controls.getInstance().getMainStage(); 22 | FileManager fileManager = FileManager.getInstance(); 23 | 24 | if (fileManager.isDirty()) { 25 | if (!fileManager.tryToSaveDirtyFile()) { 26 | return; 27 | } 28 | } 29 | 30 | Controls.getInstance().closeTimer(); 31 | 32 | FileChooser fileChooser = new FileChooser(); 33 | fileChooser.setTitle("Open Binary File"); 34 | if (initialDirectory != null) 35 | fileChooser.setInitialDirectory(initialDirectory); 36 | else 37 | fileChooser.setInitialDirectory(new File("e:\\Github\\railgun\\src\\main\\python\\rgparser\\rg")); 38 | fileChooser.getExtensionFilters().addAll( 39 | new FileChooser.ExtensionFilter("RailGun Binary File", "*.rgb")); 40 | 41 | File selectedFile = fileChooser.showOpenDialog(mainStage); 42 | 43 | if (selectedFile == null) { 44 | return; 45 | } 46 | 47 | String sourceFileName = selectedFile.getAbsolutePath(); 48 | 49 | initialDirectory = selectedFile.getParentFile(); 50 | 51 | fileManager.setBinaryFileName(sourceFileName); 52 | 53 | long length = selectedFile.length(); 54 | if (length > 256 * 1024) { 55 | System.out.println("binary file is too large"); 56 | return; 57 | } 58 | byte[] sourceContent = new byte[(int)length]; 59 | 60 | try { 61 | FileInputStream fileInputStream = new FileInputStream(selectedFile); 62 | fileInputStream.read(sourceContent); 63 | fileManager.setBinaryContent(sourceContent); 64 | 65 | fileInputStream.close(); 66 | } catch (FileNotFoundException e) { 67 | e.printStackTrace(); 68 | } catch (IOException e) { 69 | e.printStackTrace(); 70 | } 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/action/OpenFileHandler.java: -------------------------------------------------------------------------------- 1 | package org.railgun.action; 2 | 3 | import javafx.event.ActionEvent; 4 | import javafx.event.EventHandler; 5 | import javafx.scene.control.TextArea; 6 | import javafx.stage.FileChooser; 7 | import javafx.stage.Stage; 8 | import org.railgun.Controls; 9 | import org.railgun.FileManager; 10 | 11 | import java.io.*; 12 | 13 | /** 14 | * Created by hinus on 2017/11/30. 15 | */ 16 | public class OpenFileHandler implements EventHandler { 17 | private File initialDirectory = null; 18 | 19 | @Override 20 | public void handle(ActionEvent event) { 21 | Stage mainStage = Controls.getInstance().getMainStage(); 22 | TextArea ta = Controls.getInstance().getSourceCode(); 23 | 24 | FileManager fileManager = FileManager.getInstance(); 25 | 26 | if (fileManager.isDirty()) { 27 | if (!fileManager.tryToSaveDirtyFile()) { 28 | return; 29 | } 30 | } 31 | 32 | Controls.getInstance().closeTimer(); 33 | 34 | FileChooser fileChooser = new FileChooser(); 35 | fileChooser.setTitle("Open Source File"); 36 | if (initialDirectory != null) 37 | fileChooser.setInitialDirectory(initialDirectory); 38 | fileChooser.getExtensionFilters().addAll( 39 | new FileChooser.ExtensionFilter("RailGun Source File", "*.rg")); 40 | 41 | File selectedFile = fileChooser.showOpenDialog(mainStage); 42 | 43 | if (selectedFile == null) { 44 | return; 45 | } 46 | 47 | String sourceFileName = selectedFile.getAbsolutePath(); 48 | 49 | initialDirectory = selectedFile.getParentFile(); 50 | 51 | fileManager.setSourceFileName(sourceFileName); 52 | 53 | String binaryFileName = sourceFileName + "b"; 54 | 55 | File binaryFile = new File(binaryFileName); 56 | if (binaryFile != null && binaryFile.exists()) { 57 | fileManager.setBinaryFileName(binaryFileName); 58 | } 59 | 60 | long length = selectedFile.length(); 61 | if (length > 256 * 1024) { 62 | System.out.println("source code file is too large"); 63 | return; 64 | } 65 | byte[] sourceContent = new byte[(int)length]; 66 | 67 | try { 68 | FileInputStream fileInputStream = new FileInputStream(selectedFile); 69 | fileInputStream.read(sourceContent); 70 | BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(sourceContent))); 71 | 72 | String s; 73 | ta.clear(); 74 | ta.setDisable(false); 75 | while ((s = reader.readLine()) != null) { 76 | ta.appendText(s); 77 | ta.appendText("\n"); 78 | } 79 | fileManager.setDirty(false); 80 | 81 | reader.close(); 82 | fileInputStream.close(); 83 | } catch (FileNotFoundException e) { 84 | e.printStackTrace(); 85 | } catch (IOException e) { 86 | e.printStackTrace(); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/action/RunHandler.java: -------------------------------------------------------------------------------- 1 | package org.railgun.action; 2 | 3 | import javafx.event.ActionEvent; 4 | import javafx.event.EventHandler; 5 | 6 | import org.railgun.Controls; 7 | import org.railgun.FileManager; 8 | import org.railgun.Timer; 9 | import org.railgun.vm.Interpreter; 10 | 11 | /** 12 | * Created by hinus on 2017/11/30. 13 | */ 14 | public class RunHandler implements EventHandler { 15 | @Override 16 | public void handle(ActionEvent event) { 17 | Timer lastTimer = Controls.getInstance().getTimer(); 18 | if(lastTimer != null) 19 | lastTimer.exit(); 20 | 21 | Timer timer = new Timer(); 22 | Controls.getInstance().setTimer(timer); 23 | timer.setDaemon(true); 24 | timer.start(); 25 | 26 | Interpreter.getInstance().run(FileManager.getInstance().getBinaryContent()); 27 | } 28 | } -------------------------------------------------------------------------------- /src/main/java/org/railgun/action/SaveHandler.java: -------------------------------------------------------------------------------- 1 | package org.railgun.action; 2 | 3 | import javafx.event.ActionEvent; 4 | import javafx.event.EventHandler; 5 | import javafx.stage.FileChooser; 6 | import org.railgun.Controls; 7 | import org.railgun.FileManager; 8 | 9 | import java.io.*; 10 | 11 | /** 12 | * Created by hinus on 2017/11/30. 13 | */ 14 | public class SaveHandler implements EventHandler { 15 | @Override 16 | public void handle(ActionEvent event) { 17 | FileManager.getInstance().saveCurrentFile(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/action/TextChangedHandler.java: -------------------------------------------------------------------------------- 1 | package org.railgun.action; 2 | 3 | import javafx.beans.value.ChangeListener; 4 | import javafx.beans.value.ObservableValue; 5 | import org.railgun.FileManager; 6 | 7 | /** 8 | * Created by hinus on 2017/11/30. 9 | */ 10 | public class TextChangedHandler implements ChangeListener { 11 | @Override 12 | public void changed(ObservableValue observable, Object oldValue, Object newValue) { 13 | FileManager.getInstance().setDirty(true); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/canvas/View.java: -------------------------------------------------------------------------------- 1 | package org.railgun.canvas; 2 | 3 | import javafx.scene.canvas.Canvas; 4 | import javafx.scene.canvas.GraphicsContext; 5 | import org.railgun.Controls; 6 | import org.railgun.shape.Shape; 7 | 8 | import java.util.ArrayList; 9 | 10 | /** 11 | * Created by hinus on 2017/12/1. 12 | */ 13 | public class View { 14 | private static View view = new View(Controls.getInstance().getCanvas()); 15 | 16 | private Canvas canvas; 17 | private GraphicsContext graph; 18 | 19 | private View(Canvas canvas) { 20 | this.canvas = canvas; 21 | if (canvas != null) { 22 | this.graph = canvas.getGraphicsContext2D(); 23 | this.graph.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); 24 | } 25 | } 26 | 27 | public static View getView() { 28 | return view; 29 | } 30 | 31 | public void update(ArrayList shapes) { 32 | graph.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); 33 | for (Shape shape : shapes) { 34 | shape.draw(graph); 35 | } 36 | } 37 | 38 | public void drawShape(Shape shape) { 39 | shape.draw(graph); 40 | } 41 | 42 | public void clear() { 43 | if (this.graph == null) 44 | return; 45 | 46 | this.graph.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/marshal/BinaryFileParser.java: -------------------------------------------------------------------------------- 1 | package org.railgun.marshal; 2 | 3 | import org.railgun.vm.object.NoneObject; 4 | 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * Created by hinus on 2017/12/1. 9 | */ 10 | 11 | public class BinaryFileParser { 12 | static int cur; 13 | static ArrayList stringTable; 14 | 15 | public static CodeObject parse(byte[] sourceBytes) { 16 | int magicNumber; // 4 bytes; 17 | int modDate; // 4 bytes; 18 | cur = 8; 19 | stringTable = new ArrayList<>(); 20 | 21 | byte objectType = sourceBytes[cur++]; 22 | 23 | if (objectType == 'c') { 24 | return getCodeObject(sourceBytes); 25 | } 26 | 27 | return null; 28 | } 29 | 30 | static CodeObject getCodeObject(byte[] sourceBytes) { 31 | int argcount = getLong(sourceBytes); 32 | int nlocals = getLong(sourceBytes); 33 | int stacksize = getLong(sourceBytes); 34 | int flags = getLong(sourceBytes); 35 | 36 | byte[] codes = getCode(sourceBytes); 37 | 38 | ArrayList consts = getConsts(sourceBytes); 39 | ArrayList names = getNames(sourceBytes); 40 | ArrayList varnames = getVarNames(sourceBytes); 41 | ArrayList freevar = getFreeVars(sourceBytes); 42 | ArrayList cellvar = getCellVars(sourceBytes); 43 | String fileName = getFileName(sourceBytes); 44 | String name = getName(sourceBytes); 45 | int beginLineNo = getLong(sourceBytes); 46 | byte[] lnotab = getNoTable(sourceBytes); 47 | 48 | return new CodeObject(argcount, nlocals, stacksize, flags, codes, 49 | names, consts, varnames, freevar, cellvar, 50 | fileName, name, beginLineNo, lnotab); 51 | } 52 | 53 | static byte[] getNoTable(byte[] buf) { 54 | if (buf[cur] == 't' || buf[cur] == 's') { 55 | cur++; 56 | int length = getLong(buf); 57 | byte[] t = new byte[length]; 58 | for (int i = 0; i < length; i++) { 59 | t[i] = buf[cur++]; 60 | } 61 | 62 | return t; 63 | } 64 | 65 | return null; 66 | } 67 | 68 | static String getName(byte[] buf) { 69 | if (buf[cur] == 't') { 70 | cur++; 71 | String s = getString(buf); 72 | stringTable.add(s); 73 | return s; 74 | } 75 | else if (buf[cur] == 's') { 76 | cur++; 77 | return getString(buf); 78 | } 79 | else if (buf[cur] == 'R') { 80 | cur++; 81 | int index = getLong(buf); 82 | return stringTable.get(index); 83 | } 84 | 85 | return null; 86 | } 87 | 88 | static ArrayList getVarNames(byte[] buf) { 89 | if (buf[cur] == '(') { 90 | cur++; 91 | return getTuple(buf); 92 | } 93 | 94 | return null; 95 | } 96 | 97 | static ArrayList getFreeVars(byte[] buf) { 98 | if (buf[cur] == '(') { 99 | cur++; 100 | return getTuple(buf); 101 | } 102 | 103 | return null; 104 | } 105 | 106 | static ArrayList getCellVars(byte[] buf) { 107 | if (buf[cur] == '(') { 108 | cur++; 109 | return getTuple(buf); 110 | } 111 | 112 | return null; 113 | } 114 | 115 | static String getFileName(byte[] buf) { 116 | if (buf[cur] == 's') { 117 | cur++; 118 | return getString(buf); 119 | } 120 | else if (buf[cur] == 't') { 121 | cur++; 122 | String s = getString(buf); 123 | stringTable.add(s); 124 | return s; 125 | } 126 | else if (buf[cur] == 'R') { 127 | cur++; 128 | int index = getLong(buf); 129 | return stringTable.get(index); 130 | } 131 | 132 | return null; 133 | } 134 | 135 | static ArrayList getNames(byte[] buf) { 136 | if (buf[cur] == '(') { 137 | cur++; 138 | ArrayList list = getTuple(buf); 139 | return list; 140 | } 141 | return null; 142 | } 143 | 144 | static int getLong(byte[] buf) { 145 | int r = ((buf[cur + 3] & 0xff) << 24) | 146 | ((buf[cur + 2] & 0xff) << 16) | 147 | ((buf[cur + 1] & 0xff) << 8) | 148 | (buf[cur] & 0xff); 149 | cur += 4; 150 | return r; 151 | } 152 | 153 | static byte[] getCode(byte[] buf) { 154 | assert buf[cur] == 's'; 155 | cur += 1; 156 | int length = getLong(buf); 157 | byte[] code = new byte[length]; 158 | for (int i = 0; i < length; i++) { 159 | code[i] = buf[cur++]; 160 | } 161 | return code; 162 | } 163 | 164 | static ArrayList getConsts(byte[] buf) { 165 | if (buf[cur] == '(') { 166 | cur++; 167 | return getTuple(buf); 168 | } 169 | 170 | return null; 171 | } 172 | 173 | public static ArrayList getTuple(byte[] buf) { 174 | int length = getLong(buf); 175 | ArrayList list = new ArrayList(length); 176 | for (int i = 0; i < length; i++) { 177 | byte objectType = buf[cur++]; 178 | 179 | switch (objectType) { 180 | case 's': 181 | list.add(getString(buf)); 182 | break; 183 | case 'N': 184 | list.add(NoneObject.getInstance()); 185 | break; 186 | case 'i': 187 | list.add(getLong(buf)); 188 | break; 189 | case '(': 190 | list.add(getTuple(buf)); 191 | break; 192 | case 't': 193 | String s = getString(buf); 194 | list.add(s); 195 | stringTable.add(s); 196 | break; 197 | case 'c': 198 | list.add(getCodeObject(buf)); 199 | break; 200 | case 'R': 201 | list.add(getRef(buf)); 202 | break; 203 | default: 204 | throw new RuntimeException("unrecognized type: " + objectType); 205 | } 206 | } 207 | 208 | return list; 209 | } 210 | 211 | public static String getRef(byte[] buf) { 212 | int index = getLong(buf); 213 | return stringTable.get(index); 214 | } 215 | 216 | public static String getString(byte[] buf) { 217 | int length = getLong(buf); 218 | byte[] sbuf = new byte[length]; 219 | 220 | for (int i = 0; i < length; i++) { 221 | sbuf[i] = buf[cur++]; 222 | } 223 | 224 | return new String(sbuf); 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/marshal/CodeObject.java: -------------------------------------------------------------------------------- 1 | package org.railgun.marshal; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * Created by hinus on 2017/12/1. 7 | */ 8 | public class CodeObject { 9 | public int argcount; 10 | public int nlocals; 11 | public int stacksize; 12 | public int flag; 13 | 14 | public byte[] bytecodes; 15 | public ArrayList names; 16 | public ArrayList consts; 17 | public ArrayList varnames; 18 | 19 | public ArrayList freevars; 20 | public ArrayList cellvars; 21 | 22 | public String fileName; 23 | public String name; 24 | public int lineno; 25 | public byte[] notable; 26 | 27 | public CodeObject(int argcount, int nlocals, int stacksize, int flag, byte[] bytecodes, 28 | ArrayList names, ArrayList consts, ArrayList varnames, ArrayList freevars, ArrayList cellvars, 29 | String fileName, String name, int lineno, byte[] notable) { 30 | this.argcount = argcount; 31 | this.nlocals = nlocals; 32 | this.stacksize = stacksize; 33 | this.flag = flag; 34 | this.bytecodes = bytecodes; 35 | this.names = names; 36 | this.consts = consts; 37 | this.varnames = varnames; 38 | this.freevars = freevars; 39 | this.cellvars = cellvars; 40 | this.fileName = fileName; 41 | this.name = name; 42 | this.lineno = lineno; 43 | this.notable = notable; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/shape/AbstractShape.java: -------------------------------------------------------------------------------- 1 | package org.railgun.shape; 2 | 3 | 4 | import static java.lang.Math.cos; 5 | import static java.lang.Math.sin; 6 | 7 | /** 8 | * Created by hinus on 2017/11/30. 9 | */ 10 | public abstract class AbstractShape implements Shape { 11 | private int layer; 12 | 13 | protected int x; 14 | protected int y; 15 | 16 | protected double offsetX; 17 | protected double offsetY; 18 | 19 | public AbstractShape(int layer) { 20 | this.layer = layer; 21 | } 22 | 23 | public AbstractShape() { 24 | } 25 | 26 | @Override 27 | public int getLayer() { 28 | return layer; 29 | } 30 | 31 | @Override 32 | public void setLayer(int layer) { 33 | this.layer = layer; 34 | } 35 | 36 | @Override 37 | public void setX(int x) { 38 | this.x = x; 39 | } 40 | 41 | @Override 42 | public int getX() { 43 | return x; 44 | } 45 | 46 | @Override 47 | public int getY() { 48 | return y; 49 | } 50 | 51 | @Override 52 | public void setY(int y) { 53 | this.y = y; 54 | } 55 | 56 | @Override 57 | public void setOffsetX(double offsetX) { 58 | System.out.println("offset is " + offsetX + " target x is " + (this.x + offsetX)); 59 | this.offsetX = offsetX; 60 | } 61 | 62 | @Override 63 | public void setOffsetY(double offsetY) { 64 | this.offsetY = offsetY; 65 | } 66 | 67 | @Override 68 | public Shape shift(int x, int y) { 69 | this.x += x; 70 | this.y += y; 71 | 72 | return this; 73 | } 74 | 75 | @Override 76 | public Shape rotate(int x0, int y0, double angular) { 77 | int tx = (int)((x - x0) * cos(angular) - (y - y0) * sin(angular)) + x0; 78 | int ty = (int)((y - y0) * cos(angular) + (x - x0) * sin(angular)) + y0; 79 | 80 | this.x = tx; 81 | this.y = ty; 82 | 83 | this.rotate(angular); 84 | 85 | return this; 86 | } 87 | 88 | @Override 89 | public Shape rotate(double angular) { 90 | return null; 91 | } 92 | 93 | public AbstractShape copy() { 94 | return null; 95 | } 96 | 97 | @Override 98 | public Shape scale(double scalar) { 99 | return null; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/shape/Arrow.java: -------------------------------------------------------------------------------- 1 | package org.railgun.shape; 2 | 3 | import javafx.scene.canvas.GraphicsContext; 4 | 5 | /** 6 | * Created by hinus on 2017/6/4. 7 | */ 8 | public class Arrow extends AbstractShape { 9 | double x1; 10 | double y1; 11 | double x2; 12 | double y2; 13 | 14 | private Arrow(double x1, double y1, double x2, double y2) { 15 | this.x1 = x1; 16 | this.y1 = y1; 17 | this.x2 = x2; 18 | this.y2 = y2; 19 | } 20 | 21 | @Override 22 | public void draw(GraphicsContext gc) { 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/shape/Circle.java: -------------------------------------------------------------------------------- 1 | package org.railgun.shape; 2 | 3 | import javafx.scene.canvas.GraphicsContext; 4 | import javafx.scene.paint.Color; 5 | import javafx.scene.paint.Paint; 6 | 7 | /** 8 | * Created by hinus on 2017/11/30. 9 | */ 10 | public class Circle extends AbstractShape { 11 | private double width; 12 | private double height; 13 | 14 | private double centerX; 15 | private double centerY; 16 | 17 | private boolean withBorder; 18 | private double borderWidth; 19 | 20 | private boolean isFilled; 21 | private Color color; 22 | 23 | public Circle(int x, int y, double width, double height) { 24 | super(0); 25 | this.x = x; 26 | this.y = y; 27 | this.width = width; 28 | this.height = height; 29 | 30 | this.centerX = this.x + this.width / 2; 31 | this.centerY = this.y + this.height / 2; 32 | } 33 | 34 | public static Circle makeCircle(int x, int y, double width, double height, boolean isFilled) { 35 | Circle r = new Circle(x, y, width, height); 36 | r.withBorder = false; 37 | r.isFilled = isFilled; 38 | r.color = Color.rgb(127, 127, 127); 39 | return r; 40 | } 41 | 42 | public static Circle makeCircle(int x, int y, double radius, Color color) { 43 | Circle r = new Circle(x, y, radius, radius); 44 | r.withBorder = false; 45 | r.isFilled = true; 46 | r.color = color; 47 | return r; 48 | } 49 | 50 | @Override 51 | public void draw(GraphicsContext gc) { 52 | double x = this.x + this.offsetX; 53 | double y = this.y + this.offsetY; 54 | 55 | if (withBorder) { 56 | gc.strokeOval(x, y, width, height); 57 | } 58 | 59 | if (isFilled) { 60 | Paint oldColor = gc.getFill(); 61 | gc.setFill(color); 62 | gc.fillOval(x, y, width, height); 63 | gc.setFill(oldColor); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/shape/RGLine.java: -------------------------------------------------------------------------------- 1 | package org.railgun.shape; 2 | 3 | import javafx.scene.canvas.GraphicsContext; 4 | 5 | /** 6 | * Created by hinus on 2017/12/2. 7 | */ 8 | public class RGLine extends AbstractShape { 9 | private int x2; 10 | private int y2; 11 | 12 | public RGLine(int x, int y, int x2, int y2) { 13 | this.x = x; 14 | this.y = y; 15 | this.x2 = x2; 16 | this.y2 = y2; 17 | } 18 | 19 | @Override 20 | public void draw(GraphicsContext gc) { 21 | gc.strokeLine(x, y, x2, y2); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/shape/RGRoundRect.java: -------------------------------------------------------------------------------- 1 | package org.railgun.shape; 2 | 3 | import javafx.scene.canvas.GraphicsContext; 4 | 5 | /** 6 | * Created by hinus on 2017/12/2. 7 | */ 8 | public class RGRoundRect extends AbstractShape { 9 | private int arcWidth; 10 | private int arcHeight; 11 | 12 | private int width; 13 | private int height; 14 | 15 | private RGRoundRect(int x, int y, int w, int h, int arcWith, int arcHeight) { 16 | this.x = x; 17 | this.y = y; 18 | this.width = w; 19 | this.height = h; 20 | this.arcWidth = arcWith; 21 | this.arcHeight = arcHeight; 22 | } 23 | 24 | public static RGRoundRect makeRoundRect(int x, int y, int w, int h, int arcWidth, int arcHeight) { 25 | return new RGRoundRect(x, y, w, h, arcWidth, arcHeight); 26 | } 27 | 28 | @Override 29 | public void draw(GraphicsContext gc) { 30 | gc.strokeRoundRect(x, y, width, height, arcWidth, arcHeight); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/shape/RGText.java: -------------------------------------------------------------------------------- 1 | package org.railgun.shape; 2 | 3 | import javafx.scene.canvas.GraphicsContext; 4 | import javafx.scene.text.Font; 5 | 6 | /** 7 | * Created by hinus on 2017/6/4. 8 | */ 9 | public class RGText extends AbstractShape { 10 | String text; 11 | Font font; 12 | 13 | private RGText(String text, int x, int y, String fontFamily, double fontSize) { 14 | this.text = text; 15 | this.x = x; 16 | this.y = y; 17 | 18 | this.font = Font.font(fontFamily, fontSize); 19 | } 20 | 21 | public static RGText makeText(String text, int x, int y, String fontFamily, double size) { 22 | RGText t = new RGText(text, x, y, fontFamily, size); 23 | return t; 24 | } 25 | 26 | @Override 27 | public void draw(GraphicsContext gc) { 28 | double x = this.x + this.offsetX; 29 | double y = this.y + this.offsetY; 30 | 31 | Font old = gc.getFont(); 32 | gc.setFont(this.font); 33 | gc.fillText(text, x, y); 34 | gc.setFont(old); 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/java/org/railgun/shape/Rect.java: -------------------------------------------------------------------------------- 1 | package org.railgun.shape; 2 | 3 | import javafx.scene.canvas.GraphicsContext; 4 | import javafx.scene.paint.Color; 5 | import javafx.scene.paint.Paint; 6 | 7 | /** 8 | * Created by hinus on 2017/6/3. 9 | */ 10 | public class Rect extends AbstractShape { 11 | 12 | private double width; 13 | private double height; 14 | 15 | private boolean withBorder; 16 | private double borderWidth; 17 | 18 | private boolean isFilled; 19 | private Color color; 20 | 21 | public Rect(int x, int y, double width, double height) { 22 | super(0); 23 | this.x = x; 24 | this.y = y; 25 | this.width = width; 26 | this.height = height; 27 | } 28 | 29 | public static Rect makeRect(int x, int y, double width, double height, boolean isFilled, Color color) { 30 | Rect r = new Rect(x, y, width, height); 31 | r.withBorder = false; 32 | r.isFilled = isFilled; 33 | r.color = color; 34 | return r; 35 | } 36 | 37 | @Override 38 | public void draw(GraphicsContext gc) { 39 | double x = this.x + this.offsetX; 40 | double y = this.y + this.offsetY; 41 | 42 | if (withBorder) { 43 | gc.strokeRect(x, y, width, height); 44 | } 45 | 46 | if (isFilled) { 47 | Paint oldColor = gc.getFill(); 48 | gc.setFill(color); 49 | gc.fillRect(x, y, width, height); 50 | gc.setFill(oldColor); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/shape/Shape.java: -------------------------------------------------------------------------------- 1 | package org.railgun.shape; 2 | 3 | import javafx.scene.canvas.GraphicsContext; 4 | 5 | /** 6 | * Created by hinus on 2017/6/3. 7 | */ 8 | public interface Shape { 9 | void draw(GraphicsContext gc); 10 | void setX(int x); 11 | void setY(int y); 12 | 13 | int getX(); 14 | int getY(); 15 | 16 | void setOffsetX(double offsetX); 17 | void setOffsetY(double offsetY); 18 | 19 | int getLayer(); 20 | void setLayer(int layer); 21 | 22 | Shape shift(int x, int y); 23 | Shape rotate(int x0, int y0, double angular); 24 | Shape rotate(double angular); 25 | Shape scale(double scalar); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/shape/Star.java: -------------------------------------------------------------------------------- 1 | package org.railgun.shape; 2 | 3 | import javafx.scene.canvas.GraphicsContext; 4 | import javafx.scene.paint.Color; 5 | import javafx.scene.paint.Paint; 6 | 7 | import static java.lang.Math.cos; 8 | import static java.lang.Math.sin; 9 | 10 | /** 11 | * Created by hinus on 2017/12/1. 12 | */ 13 | public class Star extends AbstractShape { 14 | public double radius; 15 | public Color color; 16 | public double rotateAngular = 0.0; 17 | 18 | public double[] xs = new double[5]; 19 | public double[] ys = new double[5]; 20 | 21 | private double bx; 22 | private double by; 23 | 24 | static double angular = 72 * Math.PI / 180; 25 | 26 | public Star(int x, int y, double radius, Color color) { 27 | this.x = x; 28 | this.y = y; 29 | this.radius = radius; 30 | this.color = color; 31 | 32 | for (int i = 0; i < 5; i++) { 33 | double a = 3 * Math.PI / 2 + angular * i + rotateAngular; 34 | xs[i] = (int) (x + radius * Math.cos(a)); 35 | ys[i] = (int) (y + radius * Math.sin(a)); 36 | } 37 | 38 | bx = x; 39 | by = (int) (y + radius * Math.sin(angular / 4) / Math.sin(Math.PI - 3 * angular / 4)); 40 | 41 | int tx = (int)((bx - x) * cos(rotateAngular) - (by - y) * sin(rotateAngular)) + x; 42 | int ty = (int)((by - y) * cos(rotateAngular) + (bx - x) * sin(rotateAngular)) + y; 43 | 44 | bx = tx; 45 | by = ty; 46 | } 47 | 48 | public static Star makeStar(int x, int y, double radius) { 49 | return new Star(x, y, radius, Color.YELLOW); 50 | } 51 | 52 | @Override 53 | public void draw(GraphicsContext gc) { 54 | double[] xa = {xs[0], xs[2], bx, xs[3]}; 55 | double[] ya = {ys[0], ys[2], by, ys[3]}; 56 | 57 | double[] xb = {xs[1], xs[4], bx}; 58 | double[] yb = {ys[1], ys[4], by}; 59 | 60 | Paint oldColor = gc.getFill(); 61 | gc.setFill(this.color); 62 | gc.fillPolygon(xa, ya, 4); 63 | gc.fillPolygon(xb, yb, 3); 64 | gc.setFill(oldColor); 65 | 66 | /* 67 | gc.moveTo(xs[0], ys[0]); 68 | gc.lineTo(xs[2], ys[2]); 69 | gc.lineTo(xs[4], ys[4]); 70 | gc.lineTo(xs[1], ys[1]); 71 | gc.lineTo(xs[3], ys[3]); 72 | gc.lineTo(xs[0], ys[0]); 73 | 74 | gc.stroke();*/ 75 | } 76 | 77 | public Star copy() { 78 | return new Star(this.x, this.y, this.radius, this.color); 79 | } 80 | 81 | public Shape rotate(double rotateAngular) { 82 | this.rotateAngular = rotateAngular; 83 | 84 | for (int i = 0; i < 5; i++) { 85 | double a = 3 * Math.PI / 2 + angular * i + rotateAngular; 86 | xs[i] = (int) (x + radius * Math.cos(a)); 87 | ys[i] = (int) (y + radius * Math.sin(a)); 88 | } 89 | 90 | bx = x; 91 | by = (int) (y + radius * Math.sin(angular / 4) / Math.sin(Math.PI - 3 * angular / 4)); 92 | 93 | int tx = (int)((bx - x) * cos(rotateAngular) - (by - y) * sin(rotateAngular)) + x; 94 | int ty = (int)((by - y) * cos(rotateAngular) + (bx - x) * sin(rotateAngular)) + y; 95 | 96 | bx = tx; 97 | by = ty; 98 | 99 | return this; 100 | } 101 | 102 | public Shape shift(int x, int y) { 103 | this.x += x; 104 | this.y += y; 105 | 106 | for (int i = 0; i < 5; i++) { 107 | xs[i] += x; 108 | ys[i] += y; 109 | } 110 | 111 | bx = x; 112 | by = (int) (y + radius * Math.sin(angular / 4) / Math.sin(Math.PI - 3 * angular / 4)); 113 | 114 | int tx = (int)((bx - x) * cos(rotateAngular) - (by - y) * sin(rotateAngular)) + x; 115 | int ty = (int)((by - y) * cos(rotateAngular) + (bx - x) * sin(rotateAngular)) + y; 116 | 117 | bx = tx; 118 | by = ty; 119 | 120 | return this; 121 | } 122 | 123 | @Override 124 | public Shape scale(double scalar) { 125 | this.radius *= scalar; 126 | 127 | for (int i = 0; i < 5; i++) { 128 | double a = 3 * Math.PI / 2 + angular * i + rotateAngular; 129 | xs[i] = (int) (x + radius * Math.cos(a)); 130 | ys[i] = (int) (y + radius * Math.sin(a)); 131 | } 132 | 133 | bx = x; 134 | by = (int) (y + radius * Math.sin(angular / 4) / Math.sin(Math.PI - 3 * angular / 4)); 135 | 136 | int tx = (int)((bx - x) * cos(rotateAngular) - (by - y) * sin(rotateAngular)) + x; 137 | int ty = (int)((by - y) * cos(rotateAngular) + (bx - x) * sin(rotateAngular)) + y; 138 | 139 | bx = tx; 140 | by = ty; 141 | 142 | return this; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/Bytecode.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm; 2 | 3 | public class Bytecode { 4 | // Define org.railgun.vm.Bytecode Operator Code 5 | static final byte POP_TOP = 1; 6 | static final byte ROT_TWO = 2; 7 | static final byte ROT_THREE = 3; 8 | static final byte DUP_TOP = 4; 9 | static final byte UNARY_NEGATIVE = 11; 10 | static final byte BINARY_MULTIPLY = 20; 11 | static final byte BINARY_MODULO = 22; 12 | static final byte BINARY_SUBSCR = (byte) 25; 13 | static final byte BINARY_DIVIDE = 21; 14 | static final byte BINARY_ADD = 23; 15 | static final byte BINARY_SUBSTRACT = 24; 16 | 17 | static final byte INPLACE_ADD = 55; 18 | static final byte STORE_MAP = (byte) 54; 19 | static final byte INPLACE_SUBSTRACT = 56; 20 | static final byte INPLACE_MULTIPLY = 57; 21 | static final byte INPLACE_DIVIDE = 58; 22 | static final byte INPLACE_MODULO = 59; 23 | static final byte STORE_SUBSCR = 60; 24 | 25 | static final byte GET_ITER = 68; 26 | 27 | static final byte PRINT_ITEM = 71; 28 | static final byte PRINT_NEWLINE = 72; 29 | 30 | static final byte BREAK_LOOP = 80; 31 | static final byte LOAD_LOCALS = 82; 32 | static final byte RETURN_VALUE = 83; 33 | static final byte POP_BLOCK = 87; 34 | static final byte BUILD_CLASS = 89; 35 | 36 | // TODO: This is a separator 37 | static final byte HAVE_ARGUMENT = 90; /* Opcodes from here have an argument: */ 38 | 39 | static final byte STORE_NAME = 90; /* Index in name list */ 40 | static final byte FOR_ITER = 93; 41 | static final byte STORE_ATTR = 95; /* Index in name list */ 42 | static final byte STORE_GLOBAL = 97; 43 | static final byte DUP_TOPX = 99; /* number of items to duplicate */ 44 | static final byte LOAD_CONST = 100; /* Index in const list */ 45 | static final byte LOAD_NAME = 101; /* Index in name list */ 46 | static final byte BUILD_LIST = (byte) 103; 47 | static final byte BUILD_MAP = (byte) 105; 48 | static final byte LOAD_ATTR = 106; /* Index in name list */ 49 | static final byte COMPARE_OP = 107; /* Comparison operator */ 50 | static final byte JUMP_FORWARD = 110; /* Number of bytes to skip */ 51 | static final byte JUMP_IF_FALSE_OR_POP = 111; /* Target byte offset from beginning 52 | of code */ 53 | 54 | static final byte JUMP_ABSOLUTE = 113; 55 | static final byte POP_JUMP_IF_FALSE = 114; 56 | static final byte POP_JUMP_IF_TRUE = 115; 57 | static final byte LOAD_GLOBAL = 116; /* Index in name list */ 58 | static final byte SETUP_LOOP = 120; /* Target address (relative) */ 59 | static final byte LOAD_FAST = 124; /* Local variable number */ 60 | static final byte STORE_FAST = 125; /* Local variable number */ 61 | 62 | static final byte CALL_FUNCTION = (byte) 131; 63 | static final byte MAKE_FUNCTION = (byte) 132; 64 | 65 | public static class COMPARE { 66 | static final byte LESS = 0; 67 | static final byte LESS_EQUAL = 1; 68 | static final byte EQUAL = 2; 69 | static final byte NOT_EQUAL = 3; 70 | static final byte GREATER = 4; 71 | static final byte GREATER_EQUAL = 5; 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/Interpreter.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm; 2 | 3 | import org.railgun.Controls; 4 | import org.railgun.canvas.View; 5 | import org.railgun.marshal.BinaryFileParser; 6 | import org.railgun.marshal.CodeObject; 7 | import org.railgun.shape.*; 8 | import org.railgun.vm.intrisinc.*; 9 | import org.railgun.vm.object.*; 10 | 11 | import java.lang.reflect.InvocationTargetException; 12 | import java.lang.reflect.Method; 13 | import java.util.*; 14 | 15 | public class Interpreter { 16 | 17 | private static Interpreter instance = new Interpreter(); 18 | 19 | private static boolean x86 = false; 20 | 21 | private Interpreter() { 22 | builtinsTables.put("True", Boolean.TRUE); 23 | builtinsTables.put("False", Boolean.FALSE); 24 | 25 | builtinsTables.put("circle", new CircleMethod()); 26 | builtinsTables.put("rgb", new RgbMethod()); 27 | 28 | builtinsTables.put("line", new RGLineMethod()); 29 | builtinsTables.put("roundrect", new RGRoundRectMethod()); 30 | builtinsTables.put("rect", new RGRectMethod()); 31 | 32 | builtinsTables.put("rgtext", new RGTextMethod()); 33 | builtinsTables.put("star", new StarMethod()); 34 | 35 | builtinsTables.put("random", new RandomMethod()); 36 | builtinsTables.put("camera", new CameraMethod()); 37 | 38 | builtinsTables.put("len", new LenMethod()); 39 | 40 | builtinsTables.put("addTimer", new AddTimerMethod()); 41 | 42 | builtinsTables.put("setKeyMap", new KeyMapMethod()); 43 | builtinsTables.put("setMouseMap", new MouseMapMethod()); 44 | builtinsTables.put("setUpdate", new UpdateFunctionMethod()); 45 | builtinsTables.put("setFrameCount", new FrameCountMethod()); 46 | } 47 | 48 | public static Interpreter getInstance() { 49 | return instance; 50 | } 51 | 52 | // Global variable table 53 | private Map builtinsTables = new HashMap<>(); 54 | 55 | // Run with source bytes 56 | public void run (byte[] sourceBytes) { 57 | // Read code object from bytecode 58 | CodeObject co = BinaryFileParser.parse(sourceBytes); 59 | 60 | run(co); 61 | } 62 | 63 | // Run with code object 64 | private void run (CodeObject co) { 65 | Map globalsTable = new HashMap<>(); 66 | globalsTable.put("__name__", "__main__"); 67 | 68 | // Construct base frame 69 | RGFrameObject baseFrame = new RGFrameObject(co, globalsTable, globalsTable, 0); 70 | 71 | // Interpret current frame 72 | interpret(baseFrame, new Stack<>()); 73 | } 74 | 75 | public void run(RGFunctionObject fo, Object ... args) { 76 | // Construct base frame 77 | RGFrameObject baseFrame = new RGFrameObject(fo.co, new HashMap<>(), fo.globalsTable, 0); 78 | 79 | assert args.length == fo.argcount; 80 | 81 | // Construct arguments 82 | for (int i = 0; i < fo.argcount; ++i) { 83 | baseFrame.frameLocalsTable.put((String) fo.co.varnames.get(i), args[i]); 84 | } 85 | 86 | // Interpret current frame 87 | interpret(baseFrame, new Stack<>()); 88 | } 89 | 90 | // Interpret Instructions 91 | void interpret (RGFrameObject curFrame, Stack stackTrace) { 92 | // Program Counter 93 | int pc = curFrame.pc; 94 | // Bytecodes Array 95 | byte[] optArr = curFrame.optArr; 96 | // Bytecode Array Length 97 | int optLength = optArr.length; 98 | 99 | // Bytecode constant pools 100 | List consts = curFrame.consts; 101 | // Bytecode local variable 102 | List varnames = curFrame.varnames; 103 | Map localsTable = curFrame.frameLocalsTable; 104 | 105 | // Bytecode global variable 106 | List names = curFrame.names; 107 | Map globalsTable = curFrame.frameGlobalsTable; 108 | 109 | Stack stack = curFrame.frameStack; 110 | Stack blockStack = curFrame.blockStack; 111 | 112 | while (pc < optLength) { 113 | // TODO: Make sure current pc is at optcode, not optarg 114 | byte optcode = optArr[pc++]; 115 | boolean haveArgument = (optcode & 0xFF) >= Bytecode.HAVE_ARGUMENT; 116 | int optarg = -1; 117 | if (haveArgument) { 118 | optarg = x86 ? (optArr[pc++] & 0xFF) : ((optArr[pc++] & 0xFF) + ((optArr[pc++] & 0xFF) << 8)); 119 | } 120 | Integer lhs, rhs; 121 | Object v, w, u, attr; 122 | switch (optcode) { 123 | case Bytecode.POP_TOP: 124 | stack.pop(); 125 | break; 126 | // 2 127 | case Bytecode.ROT_TWO: 128 | v = stack.pop(); 129 | w = stack.pop(); 130 | stack.push(v); 131 | stack.push(w); 132 | break; 133 | 134 | case Bytecode.ROT_THREE: 135 | v = stack.pop(); 136 | w = stack.pop(); 137 | u = stack.pop(); 138 | 139 | stack.push(v); 140 | stack.push(u); 141 | stack.push(w); 142 | break; 143 | 144 | // 4 145 | case Bytecode.DUP_TOP: 146 | stack.push(stack.peek()); 147 | break; 148 | 149 | // 99 150 | case Bytecode.DUP_TOPX: 151 | if (optarg == 2) { 152 | v = stack.peek(); 153 | w = stack.get(stack.size() - 2); 154 | stack.push(w); 155 | stack.push(v); 156 | } 157 | else if (optarg == 3) { 158 | v = stack.peek(); 159 | w = stack.get(stack.size() - 2); 160 | u = stack.get(stack.size() - 3); 161 | stack.push(u); 162 | stack.push(w); 163 | stack.push(v); 164 | } 165 | break; 166 | 167 | case Bytecode.UNARY_NEGATIVE: 168 | v = stack.pop(); 169 | stack.push(-((Integer)v).intValue()); 170 | break; 171 | // 59 172 | case Bytecode.INPLACE_MODULO: 173 | // 22 174 | case Bytecode.BINARY_MODULO: 175 | v = stack.pop(); 176 | w = stack.pop(); 177 | /* w % v */ 178 | stack.push(((Integer)w) % ((Integer)v)); 179 | break; 180 | // 25 181 | case Bytecode.BINARY_SUBSCR: 182 | v = stack.pop(); 183 | w = stack.pop(); 184 | if(w instanceof RGObject) { 185 | stack.push(((BuiltinMethodObject)(((RGObject)w).getAttr("get"))).call((Integer)v)) ; 186 | } 187 | else 188 | { 189 | HashMap mmap = (HashMap)w; 190 | stack.push(mmap.get(v)); 191 | } 192 | break; 193 | 194 | // 57 195 | case Bytecode.INPLACE_MULTIPLY: 196 | // 20 197 | case Bytecode.BINARY_MULTIPLY: 198 | rhs = (Integer) stack.pop(); 199 | lhs = (Integer) stack.pop(); 200 | stack.push(lhs * rhs); 201 | break; 202 | // 58 203 | case Bytecode.INPLACE_DIVIDE: 204 | // 21 205 | case Bytecode.BINARY_DIVIDE: 206 | rhs = (Integer) stack.pop(); 207 | lhs = (Integer) stack.pop(); 208 | stack.push(lhs / rhs); 209 | break; 210 | // 55 211 | case Bytecode.INPLACE_ADD: 212 | // 23 213 | case Bytecode.BINARY_ADD: 214 | rhs = (Integer) stack.pop(); 215 | lhs = (Integer) stack.pop(); 216 | stack.push(lhs + rhs); 217 | break; 218 | // 56 219 | case Bytecode.INPLACE_SUBSTRACT: 220 | // 24 221 | case Bytecode.BINARY_SUBSTRACT: 222 | rhs = (Integer) stack.pop(); 223 | lhs = (Integer) stack.pop(); 224 | stack.push(lhs - rhs); 225 | break; 226 | // 60 227 | case Bytecode.STORE_SUBSCR: 228 | w = stack.pop(); 229 | v = stack.pop(); 230 | u = stack.pop(); 231 | /* v[w] = u */ 232 | if (v instanceof RGObject) { 233 | ((BuiltinMethodObject)((RGObject)v).getAttr("set")).call((Integer) w, u); 234 | } else if (v instanceof Map) { 235 | ((Map) v).put(w, u); 236 | } 237 | break; 238 | // 68 239 | case Bytecode.GET_ITER: 240 | v = stack.pop(); 241 | if (v instanceof Iterable) { 242 | stack.push(((Iterable) v).iterator()); 243 | } 244 | break; 245 | // 71 246 | case Bytecode.PRINT_ITEM: 247 | Object printObject = stack.pop(); 248 | 249 | if (printObject instanceof RGObject) { 250 | for (Object obj : ((LinkedList)(((RGObject)printObject).getAttr("elements")))) { 251 | if (obj instanceof Shape) { 252 | View.getView().drawShape((Shape)obj); 253 | } 254 | } 255 | } 256 | else if (printObject instanceof Shape) { 257 | View.getView().drawShape((Shape) printObject); 258 | } 259 | else 260 | System.out.println(printObject); 261 | 262 | break; 263 | // 72 264 | case Bytecode.PRINT_NEWLINE: 265 | break; 266 | // 80 267 | case Bytecode.BREAK_LOOP: 268 | pc = blockStack.pop(); 269 | break; 270 | 271 | // 82 272 | case Bytecode.LOAD_LOCALS: 273 | stack.push(localsTable); 274 | break; 275 | // 83 276 | case Bytecode.RETURN_VALUE: 277 | if (! stackTrace.empty()) { 278 | curFrame = stackTrace.pop(); 279 | curFrame.frameStack.push(stack.pop()); 280 | consts = curFrame.consts; 281 | optArr = curFrame.optArr; 282 | names = curFrame.names; 283 | varnames = curFrame.varnames; 284 | localsTable = curFrame.frameLocalsTable; 285 | globalsTable = curFrame.frameGlobalsTable; 286 | stack = curFrame.frameStack; 287 | blockStack = curFrame.blockStack; 288 | pc = curFrame.pc; 289 | optLength = optArr.length; 290 | } else { 291 | return; 292 | } 293 | break; 294 | // 87 295 | case Bytecode.POP_BLOCK: 296 | blockStack.pop(); 297 | break; 298 | 299 | // 89 300 | case Bytecode.BUILD_CLASS: 301 | Klass klass = new Klass((HashMap)stack.pop()); 302 | stack.push(klass); 303 | break; 304 | 305 | // TODO: Have Argument 306 | // 95 307 | case Bytecode.STORE_ATTR: 308 | v = stack.pop(); 309 | w = stack.pop(); 310 | 311 | attr = (String)names.get(optarg); 312 | 313 | if (v instanceof Shape) { 314 | if (attr.equals("x")) { 315 | ((Shape)v).setX((Integer)w); 316 | } 317 | else if (attr.equals("y")) { 318 | ((Shape)v).setY((Integer)w); 319 | } 320 | } 321 | break; 322 | 323 | // 90 324 | // TODO: STORE_NAME 将变量存到 localsTable中,需要保证 这个指令出现时 localsTable == globalsTable 325 | case Bytecode.STORE_NAME: 326 | assert localsTable == globalsTable; 327 | v = names.get(optarg); 328 | w = stack.pop(); 329 | localsTable.put((String)v, w); 330 | break; 331 | // 97 332 | case Bytecode.STORE_GLOBAL: 333 | v = names.get(optarg); 334 | w = stack.pop(); 335 | globalsTable.put((String)v, w); 336 | break; 337 | // 93 338 | case Bytecode.FOR_ITER: 339 | v = stack.peek(); 340 | if (v instanceof Iterator) { 341 | if (((Iterator) v).hasNext()) { 342 | stack.push(((Iterator) v).next()); 343 | } else { 344 | pc += optarg; 345 | stack.pop(); 346 | } 347 | } 348 | break; 349 | // 101 350 | case Bytecode.LOAD_NAME: 351 | v = names.get(optarg); 352 | 353 | // LGB: Local -> Global -> Builtins 354 | // TODO Assert: 运算顺序从左到右 355 | if (((w = localsTable.get(v)) == null) 356 | && ((w = globalsTable.get(v)) == null) 357 | && ((w = builtinsTables.get(v)) == null)) { 358 | throw new RuntimeException("Unknow name variable : " + v); 359 | } 360 | 361 | stack.push(w); 362 | break; 363 | // 116 364 | case Bytecode.LOAD_GLOBAL: 365 | v = names.get(optarg); 366 | 367 | // LGB: Global -> Builtins 368 | // TODO Assert: 运算顺序从左到右 369 | if (((w = globalsTable.get(v)) == null) 370 | && ((w = builtinsTables.get(v)) == null)) { 371 | //throw new RuntimeException("Unknow global variable : " + v + " in " + curFrame.co.name); 372 | } 373 | 374 | stack.push(w); 375 | break; 376 | // 100 377 | case Bytecode.LOAD_CONST: 378 | stack.push(consts.get(optarg)); 379 | break; 380 | // 106 381 | case Bytecode.LOAD_ATTR: 382 | v = stack.pop(); 383 | w = names.get(optarg); 384 | 385 | if (v instanceof Shape) { 386 | if (((String)w).equals("x")) { 387 | stack.push(((Shape)v).getX()); 388 | } 389 | else if (((String)w).equals("y")) { 390 | stack.push(((Shape)v).getY()); 391 | } 392 | } 393 | else if (v instanceof RGObject) { 394 | stack.push(((RGObject)v).getAttr((String)w)); 395 | } 396 | else { 397 | try { 398 | Method method = v.getClass().getMethod((String)w, double.class); 399 | stack.push(method); 400 | } catch (NoSuchMethodException e) { 401 | e.printStackTrace(); 402 | } 403 | } 404 | break; 405 | 406 | // 107 407 | case Bytecode.COMPARE_OP: 408 | // TODO: Only for Integer 409 | rhs = (Integer) stack.pop(); 410 | lhs = (Integer) stack.pop(); 411 | switch (optarg) { 412 | case Bytecode.COMPARE.LESS: 413 | stack.push(lhs < rhs); 414 | break; 415 | case Bytecode.COMPARE.LESS_EQUAL: 416 | stack.push(lhs <= rhs); 417 | break; 418 | case Bytecode.COMPARE.EQUAL: 419 | stack.push(lhs.intValue() == rhs.intValue()); 420 | break; 421 | case Bytecode.COMPARE.NOT_EQUAL: 422 | stack.push(lhs.intValue() != rhs.intValue()); 423 | break; 424 | case Bytecode.COMPARE.GREATER: 425 | stack.push(lhs > rhs); 426 | break; 427 | case Bytecode.COMPARE.GREATER_EQUAL: 428 | stack.push(lhs >= rhs); 429 | break; 430 | } 431 | break; 432 | // 110 433 | case Bytecode.JUMP_FORWARD: 434 | pc += optarg; 435 | break; 436 | 437 | // 111 438 | case Bytecode.JUMP_IF_FALSE_OR_POP: 439 | if ((Boolean) stack.peek()) { 440 | stack.pop(); 441 | } 442 | else 443 | pc = optarg; 444 | break; 445 | 446 | // 113 447 | case Bytecode.JUMP_ABSOLUTE: 448 | pc = optarg; 449 | break; 450 | // 114 451 | case Bytecode.POP_JUMP_IF_FALSE: 452 | if (! (Boolean) stack.pop()) 453 | pc = optarg; 454 | break; 455 | // 115 456 | case Bytecode.POP_JUMP_IF_TRUE: 457 | if ((Boolean) stack.pop()) 458 | pc = optarg; 459 | break; 460 | // 120 461 | case Bytecode.SETUP_LOOP: 462 | blockStack.push(pc + optarg); 463 | break; 464 | // 124 465 | case Bytecode.LOAD_FAST: 466 | v = varnames.get(optarg); 467 | w = localsTable.get(v); 468 | if (w == null) { 469 | throw new RuntimeException("Unavailable local variable " + v); 470 | } 471 | stack.push(w); 472 | break; 473 | // 125 474 | case Bytecode.STORE_FAST: 475 | v = varnames.get(optarg); 476 | w = stack.pop(); 477 | localsTable.put((String)v, w); 478 | break; 479 | // 131 480 | case Bytecode.CALL_FUNCTION: 481 | // Process Callee Arguments 482 | Object[] nextArgs = new Object[optarg]; 483 | for (int i = 0; i < optarg; ++i) { 484 | nextArgs[i] = stack.pop(); 485 | } 486 | Object o = stack.pop(); 487 | 488 | if (o instanceof InnerMethod) { 489 | stack.push(((InnerMethod)o).call(nextArgs)); 490 | } 491 | else if (o instanceof BuiltinMethodObject) { 492 | stack.push(((BuiltinMethodObject)o).call(nextArgs)); 493 | } 494 | else if (o instanceof Method) { 495 | try { 496 | stack.push(((Method)o).invoke(Controls.getInstance().getCamera(), nextArgs)); 497 | } catch (IllegalAccessException e) { 498 | e.printStackTrace(); 499 | } catch (InvocationTargetException e) { 500 | e.printStackTrace(); 501 | } 502 | } 503 | else if (o instanceof Klass) { 504 | stack.push(((Klass)o).allocate()); 505 | } 506 | else { 507 | // 保存上下文 508 | curFrame.pc = pc; 509 | stackTrace.push(curFrame); 510 | 511 | RGFunctionObject fo = (RGFunctionObject) o; 512 | int defaultcount = fo.defaultsTable.size(); 513 | int argcount = fo.argcount; 514 | // 保证参数数目的正确性 515 | if((optarg + defaultcount < argcount) || (optarg < argcount)) { 516 | throw new RuntimeException("RGException: Function " + fo.name + " Need " 517 | + argcount + " parameters, but input parameters number not match!"); 518 | } 519 | 520 | curFrame = new RGFrameObject(fo.co, new HashMap<>(), globalsTable, 0); 521 | 522 | // 切换上下文 523 | consts = curFrame.consts; 524 | names = curFrame.names; 525 | varnames = curFrame.varnames; 526 | localsTable = curFrame.frameLocalsTable; 527 | globalsTable = curFrame.frameGlobalsTable; 528 | optArr = curFrame.optArr; 529 | stack = curFrame.frameStack; 530 | blockStack = curFrame.blockStack; 531 | pc = curFrame.pc; 532 | optLength = optArr.length; 533 | // 处理调用参数 534 | // i -> stack args; j -> local args; 535 | for (int i = optarg-1, j = 0; i >= 0; --i, ++j) { 536 | localsTable.put((String) varnames.get(j), nextArgs[i]); 537 | } 538 | // 处理默认参数 539 | // i -> default args; j -> local args; 540 | for (int i = fo.argcount-optarg-1, j = optarg; j < fo.argcount; --i, ++j) { 541 | localsTable.put((String) varnames.get(j), fo.defaultsTable.get(i)); 542 | } 543 | } 544 | break; 545 | // 132 546 | case Bytecode.MAKE_FUNCTION: 547 | CodeObject co = (CodeObject) stack.pop(); // Code Object 548 | List defaultTable = new ArrayList<>(optarg); 549 | // process default arguments 550 | for(int i = 0; i < optarg; ++i) { 551 | defaultTable.add(stack.pop()); 552 | } 553 | RGFunctionObject functionObject = new RGFunctionObject(co, globalsTable, defaultTable); 554 | stack.push(functionObject); 555 | break; 556 | case Bytecode.BUILD_LIST: 557 | RGObject arr = ListKlass.getListKlass().allocate(); 558 | for (int i = 0; i < optarg; ++i) { 559 | ((BuiltinMethodObject)arr.getAttr("addFirst")).call(stack.pop()); 560 | } 561 | stack.push(arr); 562 | break; 563 | //105 564 | case Bytecode.BUILD_MAP: 565 | HashMap mp = new HashMap(); 566 | stack.push(mp); 567 | break; 568 | //54 569 | case Bytecode.STORE_MAP: 570 | Object objLeft = stack.pop(); 571 | Object objRight = stack.pop(); 572 | //mp.put(objLeft, objRight); 573 | HashMap map = (HashMap) (stack.peek()); 574 | map.put(objLeft, objRight); 575 | break; 576 | 577 | default: 578 | throw new RuntimeException("Unimplemented bytecode : " + optcode); 579 | } 580 | } 581 | } 582 | 583 | } 584 | 585 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/AddTimerMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | import org.railgun.vm.object.RGFunctionObject; 4 | import org.railgun.vm.time.UserTimer; 5 | import org.railgun.vm.time.UserTimerManager; 6 | 7 | /** 8 | * Created by hinus on 2017/12/13. 9 | */ 10 | public class AddTimerMethod implements InnerMethod { 11 | @Override 12 | public UserTimer call(Object... args) { 13 | return UserTimerManager.getManager().addTimer(((Integer)args[2]).intValue(), 14 | (RGFunctionObject) args[1], 15 | ((Boolean)args[0]).booleanValue()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/CameraMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | import javafx.scene.Camera; 4 | import javafx.scene.PerspectiveCamera; 5 | import org.railgun.Controls; 6 | 7 | import javax.sound.midi.ControllerEventListener; 8 | 9 | /** 10 | * Created by hinus on 2017/12/6. 11 | */ 12 | public class CameraMethod implements InnerMethod { 13 | @Override 14 | public Object call(Object... args) { 15 | PerspectiveCamera camera = new PerspectiveCamera(true); 16 | Controls.getInstance().getGraph3d().getChildren().add(camera); 17 | Controls.getInstance().setCamera(camera); 18 | camera.setTranslateZ(10); 19 | return camera; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/CircleMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | import javafx.scene.paint.Color; 4 | import org.railgun.shape.Circle; 5 | 6 | import java.util.concurrent.Callable; 7 | 8 | /** 9 | * Created by hinus on 2017/12/4. 10 | */ 11 | public class CircleMethod implements InnerMethod{ 12 | @Override 13 | public Circle call(Object... args) { 14 | return Circle.makeCircle((Integer) args[3], 15 | (Integer)args[2], 16 | ((Integer) args[1]).doubleValue(), 17 | (Color)args[0]); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/FrameCountMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | import org.railgun.Timer; 4 | 5 | /** 6 | * Created by hinus on 2017/12/13. 7 | */ 8 | public class FrameCountMethod implements InnerMethod { 9 | @Override 10 | public Void call(Object... args) { 11 | int frameCount = ((Integer) args[0]).intValue(); 12 | Timer.setFramesPerSecond(frameCount); 13 | return null; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/InnerMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | /** 4 | * Created by hinus on 2017/12/4. 5 | */ 6 | public interface InnerMethod { 7 | V call(Object ... args); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/KeyMapMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | import org.railgun.action.ActionController; 4 | 5 | import java.util.HashMap; 6 | 7 | /** 8 | * Created by hinus on 2017/12/7. 9 | */ 10 | public class KeyMapMethod implements InnerMethod { 11 | @Override 12 | public Void call(Object... args) { 13 | ActionController.getActionController().setKeyMap((HashMap)args[0]); 14 | return null; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/LenMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * Created by hinus on 2017/12/13. 7 | */ 8 | public class LenMethod implements InnerMethod { 9 | @Override 10 | public Integer call(Object... args) { 11 | Object o = args[0]; 12 | 13 | if (o instanceof ArrayList) { 14 | return ((ArrayList) o).size(); 15 | } 16 | 17 | return 0; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/MouseMapMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | import org.railgun.Controls; 4 | import org.railgun.action.*; 5 | 6 | import java.util.HashMap; 7 | 8 | /** 9 | * Created by hinus on 2017/12/7. 10 | */ 11 | public class MouseMapMethod implements InnerMethod { 12 | @Override 13 | public Void call(Object... args) { 14 | ActionController.getActionController().setMouseMap((HashMap)args[0]); 15 | Controls.getInstance().getCanvas().setOnMousePressed(new MouseLeftClickedHandler()); 16 | Controls.getInstance().getCanvas().setOnMouseDragEntered(new MouseDragEnterHandler()); 17 | Controls.getInstance().getCanvas().setOnMouseDragged(new MouseDragHandler()); 18 | Controls.getInstance().getCanvas().setOnMouseDragReleased(new MouseDragReleaseHandler()); 19 | return null; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/RGLineMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | import org.railgun.shape.RGLine; 4 | 5 | /** 6 | * Created by hinus on 2017/12/4. 7 | */ 8 | public class RGLineMethod implements InnerMethod { 9 | @Override 10 | public RGLine call(Object... args) { 11 | return new RGLine((Integer) args[3], 12 | (Integer)args[2], 13 | (Integer) args[1], 14 | (Integer)args[0]); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/RGRectMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | import javafx.scene.paint.Color; 4 | import org.railgun.shape.Rect; 5 | 6 | 7 | /** 8 | * Created by hinus on 2017/12/4. 9 | */ 10 | public class RGRectMethod implements InnerMethod { 11 | @Override 12 | public Rect call(Object... args) { 13 | return Rect.makeRect((Integer)args[4], 14 | (Integer)args[3], 15 | ((Integer)args[2]).doubleValue(), 16 | ((Integer)args[1]).doubleValue(), 17 | true, (Color)args[0]); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/RGRoundRectMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | import org.railgun.shape.RGRoundRect; 4 | 5 | /** 6 | * Created by hinus on 2017/12/4. 7 | */ 8 | public class RGRoundRectMethod implements InnerMethod { 9 | @Override 10 | public RGRoundRect call(Object... args) { 11 | return RGRoundRect.makeRoundRect((Integer) args[5], 12 | (Integer)args[4], (Integer)args[3], 13 | (Integer) args[2], (Integer)args[1], 14 | (Integer)args[0]); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/RGTextMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | import org.railgun.shape.RGText; 4 | 5 | /** 6 | * Created by hinus on 2017/12/4. 7 | */ 8 | public class RGTextMethod implements InnerMethod { 9 | @Override 10 | public RGText call(Object... args) { 11 | return RGText.makeText(args[4].toString(), (Integer)args[3], (Integer)args[2], 12 | (String)args[1], ((Integer)args[0]).doubleValue()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/RandomMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Created by hinus on 2017/12/4. 7 | */ 8 | public class RandomMethod implements InnerMethod { 9 | Random random = new Random(); 10 | @Override 11 | public Integer call(Object... args) { 12 | return random.nextInt((Integer)args[0]); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/RgbMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | import javafx.scene.paint.Color; 4 | 5 | /** 6 | * Created by hinus on 2017/12/4. 7 | */ 8 | public class RgbMethod implements InnerMethod { 9 | @Override 10 | public Color call(Object... args) { 11 | return Color.rgb((Integer)args[2], (Integer)args[1], (Integer)args[0]); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/StarMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | import org.railgun.shape.Star; 4 | 5 | /** 6 | * Created by hinus on 2017/12/4. 7 | */ 8 | public class StarMethod implements InnerMethod { 9 | @Override 10 | public Star call(Object... args) { 11 | return Star.makeStar((Integer)args[2], 12 | (Integer)args[1], 13 | ((Integer)args[0]).doubleValue()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/intrisinc/UpdateFunctionMethod.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.intrisinc; 2 | 3 | import org.railgun.action.ActionController; 4 | import org.railgun.vm.object.RGFunctionObject; 5 | 6 | /** 7 | * Created by hinus on 2017/12/7. 8 | */ 9 | public class UpdateFunctionMethod implements InnerMethod { 10 | @Override 11 | public Void call(Object... args) { 12 | ActionController.getActionController().setUpdateFunction((RGFunctionObject) args[0]); 13 | return null; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/object/AbstractBuiltinMethodObject.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.object; 2 | 3 | /** 4 | * Created by hinus on 2017/12/13. 5 | */ 6 | public abstract class AbstractBuiltinMethodObject extends RGObject implements BuiltinMethodObject { 7 | protected RGObject owner; 8 | protected Klass klass; 9 | 10 | @Override 11 | public void setOwner(RGObject owner) { 12 | this.owner = owner; 13 | this.klass = owner.getKlass(); 14 | } 15 | 16 | @Override 17 | public void setKlass(Klass klass) { 18 | this.klass = klass; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/object/BuiltinMethodObject.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.object; 2 | 3 | /** 4 | * Created by hinus on 2017/12/13. 5 | */ 6 | public interface BuiltinMethodObject { 7 | V call(Object... args); 8 | 9 | void setOwner(RGObject owner); 10 | 11 | void setKlass(Klass klass); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/object/Klass.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.object; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * Created by hinus on 2017/12/13. 7 | */ 8 | public class Klass { 9 | protected HashMap klassProps; 10 | 11 | public Klass() { 12 | klassProps = new HashMap<>(); 13 | } 14 | 15 | public Klass(HashMap klassProps) { 16 | this.klassProps = klassProps; 17 | } 18 | 19 | public RGObject allocate() { 20 | RGObject o = new RGObject(this, new HashMap<>()); 21 | 22 | return o; 23 | } 24 | 25 | public Object getAttr(String name) { 26 | if (klassProps.containsKey(name)) 27 | return klassProps.get(name); 28 | 29 | return null; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/object/ListKlass.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.object; 2 | 3 | import java.util.LinkedList; 4 | 5 | /** 6 | * Created by hinus on 2017/12/13. 7 | */ 8 | public class ListKlass extends Klass { 9 | public static ListKlass listKlass = new ListKlass(); 10 | 11 | public static ListKlass getListKlass() { 12 | return listKlass; 13 | } 14 | 15 | private ListKlass() { 16 | super(); 17 | klassProps.put("addFirst", new AddFirstMethod()); 18 | klassProps.put("get", new GetMethod()); 19 | klassProps.put("set", new SetMethod()); 20 | klassProps.put("length", new LengthMethod()); 21 | } 22 | 23 | public RGObject allocate() { 24 | RGObject o = super.allocate(); 25 | o.setAttr("elements", new LinkedList<>()); 26 | return o; 27 | } 28 | } 29 | 30 | class AddFirstMethod extends AbstractBuiltinMethodObject { 31 | @Override 32 | public Void call(Object... args) { 33 | ((LinkedList)this.owner.getAttr("elements")).addFirst(args[0]); 34 | return null; 35 | } 36 | } 37 | 38 | class GetMethod extends AbstractBuiltinMethodObject { 39 | @Override 40 | public Object call(Object... args) { 41 | return (Object) ((LinkedList)this.owner.getAttr("elements")).get(((Integer)args[0]).intValue()); 42 | } 43 | } 44 | 45 | class SetMethod extends AbstractBuiltinMethodObject { 46 | @Override 47 | public Void call(Object... args) { 48 | ((LinkedList)this.owner.getAttr("elements")).set(((Integer)args[0]).intValue(), args[1]); 49 | return null; 50 | } 51 | } 52 | 53 | class LengthMethod extends AbstractBuiltinMethodObject { 54 | @Override 55 | public Integer call(Object... args) { 56 | return ((LinkedList)this.owner.getAttr("elements")).size(); 57 | } 58 | } -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/object/NoneObject.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.object; 2 | 3 | /** 4 | * Created by hinus on 2017/12/15. 5 | */ 6 | public class NoneObject extends RGObject { 7 | private static NoneObject instance = new NoneObject(); 8 | 9 | public static NoneObject getInstance() { 10 | return instance; 11 | } 12 | 13 | private NoneObject() { 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/object/RGFrameObject.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.object; 2 | 3 | import org.railgun.marshal.CodeObject; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.Stack; 8 | 9 | /** 10 | * Created by YeomanSlow on 2017/12/13. 11 | */ 12 | public class RGFrameObject { 13 | public CodeObject co; 14 | public List consts; // co_consts 15 | public List names; // co_names 16 | public List varnames; // co_varnames 17 | public byte[] optArr; // co_code 18 | 19 | public Map frameGlobalsTable; // globals 20 | public Map frameLocalsTable; // locals 21 | 22 | public Stack frameStack; 23 | public Stack blockStack; 24 | public int pc; 25 | 26 | public RGFrameObject(CodeObject co, Map localsTable, Map globalsTable, int pc) { 27 | this.co = co; 28 | this.consts = co.consts; 29 | this.names = co.names; 30 | this.varnames = co.varnames; 31 | this.optArr = co.bytecodes; 32 | 33 | this.frameLocalsTable = localsTable; 34 | this.frameGlobalsTable = globalsTable; 35 | this.frameStack = new Stack<>(); 36 | this.blockStack = new Stack<>(); 37 | this.pc = pc; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/object/RGFunctionObject.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.object; 2 | 3 | import org.railgun.marshal.CodeObject; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * Created by YeomanSlow on 2017/12/13. 10 | */ 11 | public class RGFunctionObject { 12 | public CodeObject co; 13 | 14 | public Map globalsTable; 15 | public List defaultsTable; 16 | public Map closureTable; 17 | public int argcount; 18 | public String name; 19 | 20 | public RGFunctionObject(CodeObject co, Map globalsTable, List defaultsTable) { 21 | this.co = co; 22 | this.globalsTable = globalsTable; 23 | this.defaultsTable = defaultsTable; 24 | this.name = co.name; 25 | this.argcount = co.argcount; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/object/RGMethodObject.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.object; 2 | 3 | /** 4 | * Created by hinus on 2017/12/13. 5 | */ 6 | public class RGMethodObject { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/object/RGObject.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.object; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * Created by hinus on 2017/12/13. 7 | */ 8 | public class RGObject { 9 | private Klass klass; 10 | 11 | private HashMap properties; 12 | 13 | public RGObject(Klass klass, HashMap properties) { 14 | this.klass = klass; 15 | this.properties = properties; 16 | } 17 | 18 | public RGObject() { 19 | } 20 | 21 | public Klass getKlass() { 22 | return klass; 23 | } 24 | 25 | public void setKlass(Klass klass) { 26 | this.klass = klass; 27 | } 28 | 29 | public HashMap getProperties() { 30 | return properties; 31 | } 32 | 33 | public void setProperties(HashMap properties) { 34 | this.properties = properties; 35 | } 36 | 37 | public void setAttr(String name, Object value) { 38 | this.properties.put(name, value); 39 | } 40 | 41 | public Object getAttr(String name) { 42 | Object o = null; 43 | 44 | if (properties != null && properties.containsKey(name)) 45 | o = properties.get(name); 46 | else 47 | o = klass.getAttr(name); 48 | 49 | if (o != null && o instanceof BuiltinMethodObject) { 50 | ((BuiltinMethodObject) o).setOwner(this); 51 | } 52 | 53 | return o; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/time/UserTimer.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.time; 2 | 3 | import org.railgun.vm.object.Klass; 4 | import org.railgun.vm.object.RGFunctionObject; 5 | import org.railgun.vm.object.RGObject; 6 | 7 | import java.util.HashMap; 8 | 9 | /** 10 | * Created by hinus on 2017/12/13. 11 | */ 12 | public class UserTimer extends RGObject implements Comparable { 13 | private int eventFrame; 14 | private RGFunctionObject onTimer; 15 | private boolean isLoop; 16 | 17 | private boolean enabled; 18 | 19 | // the frame count in which timer is registered. 20 | private long regFrame; 21 | 22 | public UserTimer(int eventFrame, RGFunctionObject onTimer, boolean isLoop) { 23 | this.eventFrame = eventFrame; 24 | this.onTimer = onTimer; 25 | this.isLoop = isLoop; 26 | } 27 | 28 | public UserTimer() { 29 | } 30 | 31 | public UserTimer(Klass klass, HashMap properties) { 32 | super(klass, properties); 33 | } 34 | 35 | public long getRegFrame() { 36 | return regFrame; 37 | } 38 | 39 | public void setRegFrame(long regFrame) { 40 | this.regFrame = regFrame; 41 | } 42 | 43 | public int getEventFrame() { 44 | return eventFrame; 45 | } 46 | 47 | public void setEventFrame(int eventFrame) { 48 | this.eventFrame = eventFrame; 49 | } 50 | 51 | public RGFunctionObject getOnTimer() { 52 | return onTimer; 53 | } 54 | 55 | public void setOnTimer(RGFunctionObject onTimer) { 56 | this.onTimer = onTimer; 57 | } 58 | 59 | public boolean isLoop() { 60 | return isLoop; 61 | } 62 | 63 | public void setLoop(boolean loop) { 64 | isLoop = loop; 65 | } 66 | 67 | @Override 68 | public int compareTo(UserTimer o) { 69 | if ((regFrame + eventFrame) < (o.getRegFrame() + o.getEventFrame())) 70 | return 1; 71 | else if ((regFrame + eventFrame) == (o.getRegFrame() + o.getEventFrame())) 72 | return 0; 73 | else 74 | return -1; 75 | } 76 | 77 | public boolean isEnabled() { 78 | return enabled; 79 | } 80 | 81 | public void setEnabled(boolean enabled) { 82 | this.enabled = enabled; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/time/UserTimerKlass.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.time; 2 | 3 | import org.railgun.vm.object.AbstractBuiltinMethodObject; 4 | import org.railgun.vm.object.Klass; 5 | import org.railgun.vm.object.RGObject; 6 | 7 | import java.util.HashMap; 8 | 9 | /** 10 | * Created by hinus on 2017/12/14. 11 | */ 12 | public class UserTimerKlass extends Klass { 13 | private static UserTimerKlass instance = new UserTimerKlass(); 14 | 15 | public static UserTimerKlass getInstance() { 16 | return instance; 17 | } 18 | 19 | private UserTimerKlass() { 20 | super(); 21 | this.klassProps.put("stop", new UserTimerStopMethod()); 22 | } 23 | 24 | @Override 25 | public RGObject allocate() { 26 | return new UserTimer(this, null); 27 | } 28 | } 29 | 30 | class UserTimerStopMethod extends AbstractBuiltinMethodObject { 31 | @Override 32 | public Void call(Object... args) { 33 | ((UserTimer)this.owner).setEnabled(false); 34 | return null; 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/java/org/railgun/vm/time/UserTimerManager.java: -------------------------------------------------------------------------------- 1 | package org.railgun.vm.time; 2 | 3 | import org.railgun.Timer; 4 | import org.railgun.vm.Interpreter; 5 | import org.railgun.vm.object.RGFunctionObject; 6 | 7 | import java.util.PriorityQueue; 8 | 9 | /** 10 | * Created by hinus on 2017/12/13. 11 | */ 12 | public class UserTimerManager { 13 | private static UserTimerManager manager = new UserTimerManager(); 14 | 15 | private PriorityQueue timerQueue; 16 | 17 | private UserTimerManager() { 18 | timerQueue = new PriorityQueue<>(); 19 | } 20 | 21 | public static UserTimerManager getManager() { 22 | return manager; 23 | } 24 | 25 | public UserTimer addTimer(int frame, RGFunctionObject onTimer, boolean isLoop) { 26 | UserTimer u = (UserTimer) UserTimerKlass.getInstance().allocate(); 27 | u.setEventFrame(frame); 28 | u.setOnTimer(onTimer); 29 | u.setLoop(isLoop); 30 | u.setEnabled(true); 31 | 32 | u.setRegFrame(Timer.frameCnt); 33 | timerQueue.add(u); 34 | 35 | return u; 36 | } 37 | 38 | public void refresh(long frameCnt) { 39 | if (timerQueue.isEmpty()) 40 | return; 41 | 42 | UserTimer topTimer = timerQueue.peek(); 43 | if (frameCnt < topTimer.getRegFrame() + topTimer.getEventFrame()) 44 | return; 45 | 46 | while (topTimer.getRegFrame() + topTimer.getEventFrame() < frameCnt) { 47 | if (topTimer.isEnabled()) { 48 | Interpreter.getInstance().run(topTimer.getOnTimer()); 49 | } 50 | 51 | timerQueue.remove(); 52 | 53 | if (topTimer.isEnabled() && topTimer.isLoop()) { 54 | topTimer.setRegFrame(frameCnt); 55 | timerQueue.add(topTimer); 56 | } 57 | 58 | if (timerQueue.isEmpty()) 59 | break; 60 | 61 | topTimer = timerQueue.peek(); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/python/rgparser/README.md: -------------------------------------------------------------------------------- 1 | Hello pyparser -------------------------------------------------------------------------------- /src/main/python/rgparser/ast2pyc.py: -------------------------------------------------------------------------------- 1 | import marshal 2 | import py_compile 3 | import time 4 | import ast 5 | 6 | #codeobject = compile("body=[ClassDef(name='A', bases=[Name(id='object', ctx=Load())], body=[FunctionDef(name='__init__', args=arguments(args=[Name(id='self', ctx=Param()), Name(id='value', ctx=Param())], vararg=None, kwarg=None, defaults=[]), body=[Assign(targets=[Attribute(value=Name(id='self', ctx=Load()), attr='v', ctx=Store())], value=Name(id='value', ctx=Load()))], decorator_list=[]), FunctionDef(name='p', args=arguments(args=[Name(id='self', ctx=Param())], vararg=None, kwarg=None, defaults=[]), body=[Print(dest=None, values=[Attribute(value=Name(id='self', ctx=Load()), attr='v', ctx=Load())], nl=True), Return()], decorator_list=[])], decorator_list=[]), Assign(targets=[Name(id='a', ctx=Store())], value=Call(func=Name(id='A', ctx=Load()), args=[Num(n=1)], keywords=[], starargs=None, kwargs=None)), Expr(value=Call(func=Attribute(value=Name(id='a', ctx=Load()), attr='p', ctx=Load()), args=[], keywords=[], starargs=None, kwargs=None))]", '', 'exec') 7 | codeobject = compile(ast.parse('print 3+3*2'), '', 'exec') 8 | print codeobject 9 | with open('output.pyc', 'wb') as fc: 10 | fc.write('\0\0\0\0') 11 | py_compile.wr_long(fc, long(time.time())) 12 | marshal.dump(codeobject, fc) 13 | fc.flush() 14 | fc.seek(0, 0) 15 | fc.write(py_compile.MAGIC) -------------------------------------------------------------------------------- /src/main/python/rgparser/check_ast.py: -------------------------------------------------------------------------------- 1 | import ast 2 | 3 | def main(): 4 | f = open("init.py", 'r') 5 | s = f.read() 6 | 7 | n = ast.parse(s) 8 | print ast.dump(n) 9 | 10 | return 11 | 12 | if __name__ == '__main__': 13 | main() 14 | -------------------------------------------------------------------------------- /src/main/python/rgparser/compile.bat: -------------------------------------------------------------------------------- 1 | D: 2 | cd hack 3 | python D:\hack\ddl.py D:\hack\test.rg 4 | -------------------------------------------------------------------------------- /src/main/python/rgparser/ddlib/__init__.py: -------------------------------------------------------------------------------- 1 | # Dragon Sword Package 2 | # Author: gzxuwei@corp.netease.com 3 | 4 | __all__ = ['yacc', 'ddlex'] 5 | -------------------------------------------------------------------------------- /src/main/python/rgparser/ddlib/assem.py: -------------------------------------------------------------------------------- 1 | #-*- coding: UTF-8 -*- 2 | # 3 | # ----------------------------------------------------------------------------- 4 | # bytecode generators for python 5 | # author : gzxuwei@corp.netease.com 6 | # date : 2015-06-05 7 | # ----------------------------------------------------------------------------- 8 | 9 | import opcode 10 | import types 11 | 12 | class DDCodeGenerator(object): 13 | def __init__(self): 14 | self.argcount = 0 15 | self.nlocals = 0 16 | self.stacksize = 0 17 | self.flags = 0 18 | 19 | self.consts = () 20 | self.names = () 21 | self.varnames = () 22 | 23 | self.filename = "" 24 | self.name = "" 25 | 26 | self.freevars = () 27 | self.cellvars = () 28 | 29 | self.lnotab = LineNumberTable() 30 | 31 | return 32 | 33 | def add_code(self, instruction): 34 | self.lnotab.add_code(instruction) 35 | return 36 | 37 | def get_code(self): 38 | return self.lnotab.get_code() 39 | 40 | def make_code_object(self): 41 | co = types.CodeType(self.argcount, self.nlocals, self.stacksize, self.flags, 42 | self.get_code(), self.consts, self.names, self.varnames, 43 | self.filename, self.name, 44 | self.lnotab.firstline, 45 | self.lnotab.getTable(), self.freevars, self.cellvars) 46 | 47 | return co 48 | 49 | 50 | class LineNumberTable(object): 51 | def __init__(self): 52 | super(LineNumberTable, self).__init__() 53 | self.firstline = 0 54 | self.code = [] 55 | self.lnotab = [] 56 | self.inst_offset = 0 57 | 58 | return 59 | 60 | def getTable(self): 61 | return ''.join(self.lnotab) 62 | 63 | def add_code(self, instruction): 64 | str_opcode = instruction[0] 65 | 66 | if str_opcode == "SET_LINENO": 67 | if self.firstline == 0: 68 | self.firstline = instruction[1] 69 | self.lastline = self.firstline 70 | return 71 | else: 72 | line_offset = instruction[1] - self.lastline 73 | self.lastline = instruction[1] 74 | self.lnotab.append(chr(self.inst_offset)) 75 | self.lnotab.append(chr(line_offset)) 76 | self.inst_offset = 0 77 | return 78 | 79 | int_opcode = opcode.opmap.get(str_opcode, -1) 80 | 81 | if int_opcode < 0: 82 | return 83 | 84 | self.code.append(chr(int_opcode)) 85 | self.inst_offset += 1 86 | 87 | if len(instruction) > 1: 88 | for arg in instruction[1:]: 89 | hi, lo = divmod(arg, 256) 90 | 91 | self.code.append(chr(lo)) 92 | self.code.append(chr(hi)) 93 | self.inst_offset += 2 94 | 95 | return 96 | 97 | def get_code(self): 98 | return ''.join(self.code) 99 | 100 | co = None 101 | 102 | def foo(): 103 | g = DDCodeGenerator() 104 | g.name = "g" 105 | g.filename = "" 106 | g.consts = (1, None) 107 | g.stacksize = 1 108 | g.co_flags = 19 109 | g.freevars = ('x', ) 110 | 111 | g.add_code(('SET_LINENO', 5)) 112 | g.add_code(('LOAD_DEREF', 0)) 113 | g.add_code(('LOAD_CONST', 0)) 114 | g.add_code(('INPLACE_ADD', )) 115 | g.add_code(('STORE_DEREF', 0)) 116 | g.add_code(('SET_LINENO', 6)) 117 | g.add_code(('LOAD_DEREF', 0)) 118 | g.add_code(('PRINT_ITEM', )) 119 | g.add_code(('PRINT_NEWLINE', )) 120 | g.add_code(('LOAD_CONST', 1)) 121 | g.add_code(('RETURN_VALUE', )) 122 | 123 | cog = g.make_code_object() 124 | 125 | f = DDCodeGenerator() 126 | f.name = "f" 127 | f.filename = "" 128 | f.consts = (1, cog, None) 129 | f.stacksize = 2 130 | f.co_flags = 3 131 | f.cellvars = ('x', ) 132 | f.varnames = ('g', ) 133 | 134 | f.add_code(('SET_LINENO', 2)) 135 | f.add_code(('LOAD_CONST', 0)) 136 | f.add_code(('STORE_DEREF', 0)) 137 | 138 | f.add_code(('SET_LINENO', 3)) 139 | f.add_code(('LOAD_DEREF', 0)) 140 | f.add_code(('PRINT_ITEM', )) 141 | f.add_code(('PRINT_NEWLINE', )) 142 | 143 | f.add_code(('SET_LINENO', 4)) 144 | f.add_code(('LOAD_CLOSURE', 0)) 145 | f.add_code(('BUILD_TUPLE', 1)) 146 | f.add_code(('LOAD_CONST', 1)) 147 | f.add_code(('MAKE_CLOSURE', 0)) 148 | f.add_code(('STORE_FAST', 0)) 149 | f.add_code(('LOAD_FAST', 1)) 150 | f.add_code(('RETURN_VALUE', )) 151 | 152 | cof = f.make_code_object() 153 | 154 | m = DDCodeGenerator() 155 | 156 | m.name = "" 157 | m.filename = "" 158 | m.consts = (cof, None) 159 | m.names = ('f', ) 160 | m.stacksize = 1 161 | m.flags = 64 162 | 163 | m.add_code(('SET_LINENO', 1)) 164 | m.add_code(('LOAD_CONST', 0)) 165 | m.add_code(('MAKE_FUNCTION', 0)) 166 | m.add_code(('STORE_NAME', 0)) 167 | m.add_code(('SET_LINENO', 7)) 168 | m.add_code(('LOAD_CONST', 1)) 169 | m.add_code(('RETURN_VALUE', )) 170 | 171 | global co 172 | co = m.make_code_object() 173 | 174 | return 175 | 176 | -------------------------------------------------------------------------------- /src/main/python/rgparser/ddlib/ddlex.py: -------------------------------------------------------------------------------- 1 | #-*- coding: UTF-8 -*- 2 | # 3 | # ----------------------------------------------------------------------------- 4 | # parser for dragon sword 5 | # author : gzxuwei@corp.netease.com 6 | # date : 2014-11-03 7 | # ----------------------------------------------------------------------------- 8 | 9 | import tokenize as tk 10 | import ast 11 | 12 | token_types = { 13 | tk.INDENT : ('INDENT', ), 14 | tk.DEDENT : ('DEDENT', ), 15 | tk.NAME : ('NAME', ), 16 | tk.STRING : ('STRING', ), 17 | tk.ENDMARKER : ('ENDMARKER', ), 18 | tk.NEWLINE : ('NEWLINE', ), 19 | tk.NUMBER : ('NUMBER', ), 20 | tk.COMMENT : ('COMMENT', ), 21 | } 22 | 23 | reserved = { 24 | 25 | #'draw' : 'TAG_DRAW', 26 | 'class' : 'TAG_CLASS', 27 | 'def' : 'TAG_DEF', 28 | 'lambda' : 'TAG_LAMBDA', 29 | 'from' : 'TAG_FROM', 30 | 'as' : 'TAG_AS', 31 | 'global' : 'TAG_GLOBAL', 32 | 33 | 'if' : 'TAG_IF', 34 | 'else' : 'TAG_ELSE', 35 | 'elif' : 'TAG_ELIF', 36 | 'for' : 'TAG_FOR', 37 | 'while' : 'TAG_WHILE', 38 | 'try' : 'TAG_TRY', 39 | 'except' : 'TAG_EXCEPT', 40 | 'finally' : 'TAG_FINALLY', 41 | 42 | 'or' : 'TAG_OR', 43 | 'and' : 'TAG_AND', 44 | 'not' : 'TAG_NOT', 45 | 'in' : 'TAG_IN', 46 | 'is' : 'TAG_IS', 47 | 48 | 'pass' : 'TAG_PASS', 49 | 'del' : 'TAG_DEL', 50 | 'break' : 'TAG_BREAK', 51 | 'continue' : 'TAG_CONTINUE', 52 | 'draw' : 'TAG_DRAW', 53 | 'return' : 'TAG_RETURN', 54 | 'raise' : 'TAG_RAISE', 55 | 'exec' : 'TAG_EXEC', 56 | 'assert' : 'TAG_ASSERT', 57 | 'yield' : 'TAG_YIELD', 58 | 'import' : 'TAG_IMPORT', 59 | } 60 | 61 | op_types = { 62 | ':' : ':', 63 | '(' : '(', 64 | ')' : ')', 65 | '{' : '{', 66 | '}' : '}', 67 | '[' : '[', 68 | ']' : ']', 69 | '<' : '<', 70 | '>' : '>', 71 | '=' : '=', 72 | ',' : ',', 73 | '.' : '.', 74 | '%' : '%', 75 | '+' : '+', 76 | '-' : '-', 77 | '|' : '|', 78 | '&' : '&', 79 | '^' : '^', 80 | '*' : '*', 81 | '/' : '/', 82 | '==' : 'OP_EQ', 83 | '<=' : 'OP_LE', 84 | '>=' : 'OP_GE', 85 | '!=' : 'OP_NE', 86 | '<>' : 'OP_NNE', 87 | '<<' : 'OP_LEFT_SHIFT', 88 | '>>' : 'OP_RIGHT_SHIFT', 89 | '//' : 'OP_EXACT_DIVISION', 90 | '**' : 'OP_POWER', 91 | '+=' : 'ADD_ASN', 92 | '-=' : 'SUB_ASN', 93 | '*=' : 'MUL_ASN', 94 | '/=' : 'DIV_ASN', 95 | '%=' : 'MOD_ASN', 96 | '&=' : 'AND_ASN', 97 | '|=' : 'OR_ASN', 98 | '^=' : 'XOR_ASN', 99 | '<<=' : 'LSHIFT_ASN', 100 | '>>=' : 'RSHIFT_ASN', 101 | '**=' : 'POW_ASN', 102 | '//=' : 'FDIV_ASN', 103 | } 104 | 105 | # Token class. This class is used to represent the tokens produced. 106 | class LexToken(object): 107 | def __str__(self): 108 | return "LexToken(%s,%r,%d,%d)" % (self.type,self.value,self.lineno,self.lexpos) 109 | 110 | def __repr__(self): 111 | return str(self) 112 | 113 | class DDLexer(object): 114 | def __init__(self, input_file): 115 | super(DDLexer, self).__init__() 116 | 117 | self.stopped = False 118 | self.lineno = 0 119 | 120 | self.gt = tk.generate_tokens(input_file.readline) 121 | 122 | def token(self): 123 | if self.stopped: 124 | return None 125 | 126 | if not self.gt: 127 | return None 128 | 129 | _type, _value, _pos_begin, _pos_end, __ = self.gt.next() 130 | 131 | # 如果是续行的情况,就直接跳过 132 | while _type in (tk.NL, tk.COMMENT, tk.INDENT, tk.DEDENT, tk.NEWLINE): 133 | _type, _value, _pos_begin, _pos_end, __ = self.gt.next() 134 | 135 | 136 | if _type == tk.OP and _value == ';': 137 | token = LexToken() 138 | token.type = tk.NEWLINE 139 | token.value = _value 140 | token.lineno = _pos_begin[0] 141 | token.lexpos = _pos_begin[1] 142 | 143 | else: 144 | if _type == tk.ENDMARKER: 145 | self.stopped = True 146 | 147 | token = LexToken() 148 | token.type = _type 149 | token.value = _value 150 | token.lineno = _pos_begin[0] 151 | token.lexpos = _pos_begin[1] 152 | 153 | self.lineno = _pos_end[0] 154 | 155 | self._post_process(token) 156 | 157 | return token 158 | 159 | # 后处理 160 | def _post_process(self, token): 161 | if token.type == tk.NAME: 162 | token.type = reserved.get(token.value.lower(), 'NAME') 163 | 164 | elif token.type == tk.OP: 165 | token.type = op_types[token.value] 166 | # print token 167 | 168 | else: 169 | token.type = token_types[token.type][0] 170 | #print token 171 | 172 | return 173 | 174 | def input(self, _nothing): 175 | return 176 | -------------------------------------------------------------------------------- /src/main/python/rgparser/ddlib/ddyacc.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinus/railgun/3778549acaf30bade0aab9bdc47380a3a6eb20ad/src/main/python/rgparser/ddlib/ddyacc.py -------------------------------------------------------------------------------- /src/main/python/rgparser/dsparserlib/__init__.py: -------------------------------------------------------------------------------- 1 | # Dragon Sword Package 2 | # Author: gzxuwei@corp.netease.com 3 | 4 | __all__ = ['lex', 'yacc', 'element'] 5 | -------------------------------------------------------------------------------- /src/main/python/rgparser/dsparserlib/pylex.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinus/railgun/3778549acaf30bade0aab9bdc47380a3a6eb20ad/src/main/python/rgparser/dsparserlib/pylex.py -------------------------------------------------------------------------------- /src/main/python/rgparser/env.cmd: -------------------------------------------------------------------------------- 1 | set path=%path%;C:\Program Files (x86)\Git\bin;C:\Program Files (x86)\Python -------------------------------------------------------------------------------- /src/main/python/rgparser/py_src/Grammar: -------------------------------------------------------------------------------- 1 | # Grammar for Python 2 | 3 | # Note: Changing the grammar specified in this file will most likely 4 | # require corresponding changes in the parser module 5 | # (../Modules/parsermodule.c). If you can't make the changes to 6 | # that module yourself, please co-ordinate the required changes 7 | # with someone who can; ask around on python-dev for help. Fred 8 | # Drake will probably be listening there. 9 | 10 | # NOTE WELL: You should also follow all the steps listed in PEP 306, 11 | # "How to Change Python's Grammar" 12 | 13 | # Start symbols for the grammar: 14 | # single_input is a single interactive statement; 15 | # file_input is a module or sequence of commands read from an input file; 16 | # eval_input is the input for the eval() and input() functions. 17 | # NB: compound_stmt in single_input is followed by extra NEWLINE! 18 | single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE 19 | file_input: (NEWLINE | stmt)* ENDMARKER 20 | eval_input: testlist NEWLINE* ENDMARKER 21 | 22 | decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE 23 | decorators: decorator+ 24 | decorated: decorators (classdef | funcdef) 25 | funcdef: 'def' NAME parameters ':' suite 26 | parameters: '(' [varargslist] ')' 27 | varargslist: ((fpdef ['=' test] ',')* 28 | ('*' NAME [',' '**' NAME] | '**' NAME) | 29 | fpdef ['=' test] (',' fpdef ['=' test])* [',']) 30 | fpdef: NAME | '(' fplist ')' 31 | fplist: fpdef (',' fpdef)* [','] 32 | 33 | stmt: simple_stmt | compound_stmt 34 | simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE 35 | small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | 36 | import_stmt | global_stmt | exec_stmt | assert_stmt) 37 | expr_stmt: testlist (augassign (yield_expr|testlist) | 38 | ('=' (yield_expr|testlist))*) 39 | augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | 40 | '<<=' | '>>=' | '**=' | '//=') 41 | # For normal assignments, additional restrictions enforced by the interpreter 42 | print_stmt: 'print' ( [ test (',' test)* [','] ] | 43 | '>>' test [ (',' test)+ [','] ] ) 44 | del_stmt: 'del' exprlist 45 | pass_stmt: 'pass' 46 | flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt 47 | break_stmt: 'break' 48 | continue_stmt: 'continue' 49 | return_stmt: 'return' [testlist] 50 | yield_stmt: yield_expr 51 | raise_stmt: 'raise' [test [',' test [',' test]]] 52 | import_stmt: import_name | import_from 53 | import_name: 'import' dotted_as_names 54 | import_from: ('from' ('.'* dotted_name | '.'+) 55 | 'import' ('*' | '(' import_as_names ')' | import_as_names)) 56 | import_as_name: NAME ['as' NAME] 57 | dotted_as_name: dotted_name ['as' NAME] 58 | import_as_names: import_as_name (',' import_as_name)* [','] 59 | dotted_as_names: dotted_as_name (',' dotted_as_name)* 60 | dotted_name: NAME ('.' NAME)* 61 | global_stmt: 'global' NAME (',' NAME)* 62 | exec_stmt: 'exec' expr ['in' test [',' test]] 63 | assert_stmt: 'assert' test [',' test] 64 | 65 | compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated 66 | if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] 67 | while_stmt: 'while' test ':' suite ['else' ':' suite] 68 | for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] 69 | try_stmt: ('try' ':' suite 70 | ((except_clause ':' suite)+ 71 | ['else' ':' suite] 72 | ['finally' ':' suite] | 73 | 'finally' ':' suite)) 74 | with_stmt: 'with' with_item (',' with_item)* ':' suite 75 | with_item: test ['as' expr] 76 | # NB compile.c makes sure that the default except clause is last 77 | except_clause: 'except' [test [('as' | ',') test]] 78 | suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT 79 | 80 | # Backward compatibility cruft to support: 81 | # [ x for x in lambda: True, lambda: False if x() ] 82 | # even while also allowing: 83 | # lambda x: 5 if x else 2 84 | # (But not a mix of the two) 85 | testlist_safe: old_test [(',' old_test)+ [',']] 86 | old_test: or_test | old_lambdef 87 | old_lambdef: 'lambda' [varargslist] ':' old_test 88 | 89 | test: or_test ['if' or_test 'else' test] | lambdef 90 | or_test: and_test ('or' and_test)* 91 | and_test: not_test ('and' not_test)* 92 | not_test: 'not' not_test | comparison 93 | comparison: expr (comp_op expr)* 94 | comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' 95 | expr: xor_expr ('|' xor_expr)* 96 | xor_expr: and_expr ('^' and_expr)* 97 | and_expr: shift_expr ('&' shift_expr)* 98 | shift_expr: arith_expr (('<<'|'>>') arith_expr)* 99 | arith_expr: term (('+'|'-') term)* 100 | term: factor (('*'|'/'|'%'|'//') factor)* 101 | factor: ('+'|'-'|'~') factor | power 102 | power: atom trailer* ['**' factor] 103 | atom: ('(' [yield_expr|testlist_comp] ')' | 104 | '[' [listmaker] ']' | 105 | '{' [dictorsetmaker] '}' | 106 | '`' testlist1 '`' | 107 | NAME | NUMBER | STRING+) 108 | listmaker: test ( list_for | (',' test)* [','] ) 109 | testlist_comp: test ( comp_for | (',' test)* [','] ) 110 | lambdef: 'lambda' [varargslist] ':' test 111 | trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME 112 | subscriptlist: subscript (',' subscript)* [','] 113 | subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] 114 | sliceop: ':' [test] 115 | exprlist: expr (',' expr)* [','] 116 | testlist: test (',' test)* [','] 117 | dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) | 118 | (test (comp_for | (',' test)* [','])) ) 119 | 120 | classdef: 'class' NAME ['(' [testlist] ')'] ':' suite 121 | 122 | arglist: (argument ',')* (argument [','] 123 | |'*' test (',' argument)* [',' '**' test] 124 | |'**' test) 125 | # The reason that keywords are test nodes instead of NAME is that using NAME 126 | # results in an ambiguity. ast.c makes sure it's a NAME. 127 | argument: test [comp_for] | test '=' test 128 | 129 | list_iter: list_for | list_if 130 | list_for: 'for' exprlist 'in' testlist_safe [list_iter] 131 | list_if: 'if' old_test [list_iter] 132 | 133 | comp_iter: comp_for | comp_if 134 | comp_for: 'for' exprlist 'in' or_test [comp_iter] 135 | comp_if: 'if' old_test [comp_iter] 136 | 137 | testlist1: test (',' test)* 138 | 139 | # not used in grammar, but may appear in "node" passed from Parser to Compiler 140 | encoding_decl: NAME 141 | 142 | yield_expr: 'yield' [testlist] 143 | -------------------------------------------------------------------------------- /src/main/python/rgparser/pyparser.py: -------------------------------------------------------------------------------- 1 | #-*- coding: UTF-8 -*- 2 | # 3 | # ----------------------------------------------------------------------------- 4 | # parser for dragon sword 5 | # author : gzxuwei@corp.netease.com 6 | # date : 2013-11-03 7 | # ----------------------------------------------------------------------------- 8 | 9 | import sys, re 10 | sys.path.insert(0,"./dsparserlib") 11 | 12 | if sys.version_info[0] >= 3: 13 | raw_input = input 14 | 15 | tokens = ( 16 | 'DEDENT', 17 | 'INDENT', 18 | 'NEWLINE', 19 | 'ENDMARKER', 20 | 21 | 'TAG_CLASS', 22 | 'TAG_DEF', 23 | 'TAG_LAMBDA', 24 | 'TAG_FROM', 25 | 'TAG_AS', 26 | 'TAG_GLOBAL', 27 | 28 | 'TAG_IF', 29 | 'TAG_ELSE', 30 | 'TAG_ELIF', 31 | 'TAG_FOR', 32 | 'TAG_WHILE', 33 | 34 | 'TAG_PRINT', 35 | 'TAG_PASS', 36 | 'TAG_DEL', 37 | 'TAG_BREAK', 38 | 'TAG_CONTINUE', 39 | 'TAG_RETURN', 40 | 'TAG_RAISE', 41 | 'TAG_EXEC', 42 | 'TAG_ASSERT', 43 | 'TAG_YIELD', 44 | 'TAG_IMPORT', 45 | 46 | 'TAG_OR', 47 | 'TAG_AND', 48 | 'TAG_NOT', 49 | 'TAG_IN', 50 | 'TAG_IS', 51 | 52 | 'OP_LE', 53 | 'OP_GE', 54 | 'OP_EQ', 55 | 'OP_NE', 56 | 'OP_NNE', 57 | 58 | 'OP_LEFT_SHIFT', 59 | 'OP_RIGHT_SHIFT', 60 | 'OP_EXACT_DIVISION', 61 | 'OP_POWER', 62 | 63 | 'NAME', 64 | 'FLOAT', 65 | 'INTEGER', 66 | ) 67 | 68 | 69 | literals = [':', '(', ')', '{', '}', '[', ']', '<', '>', '='] 70 | 71 | def p_file_input(p): 72 | '''file_input : ENDMARKER 73 | | file_content ENDMARKER''' 74 | print 'what the fuck!', p[0], p[1] 75 | return 76 | 77 | def p_file_content(p): 78 | '''file_content : file_content NEWLINE 79 | | file_content stmt 80 | | NEWLINE 81 | | stmt''' 82 | 83 | return 84 | 85 | def p_classdef(p): 86 | '''classdef : TAG_CLASS NAME ":" suite 87 | | TAG_CLASS NAME "(" testlist ")" ":" suite 88 | | TAG_CLASS NAME "(" ")" ":" suite''' 89 | 90 | print 'find a class defination' 91 | 92 | return 93 | 94 | def p_exprlist(p): 95 | '''exprlist : expr 96 | | exprlist "," expr''' 97 | 98 | return 99 | 100 | def p_expr(p): 101 | '''expr : xor_expr 102 | | expr "|" xor_expr''' 103 | 104 | return 105 | 106 | def p_xor_expr(p): 107 | '''xor_expr : and_expr 108 | | and_expr "^" xor_expr_listing''' 109 | 110 | def p_xor_expr_listing(p): 111 | '''xor_expr_listing : and_expr 112 | | and_expr "^" xor_expr_listing''' 113 | 114 | return 115 | 116 | def p_and_expr(p): 117 | '''and_expr : shift_expr 118 | | shift_expr "&" and_expr_listing''' 119 | 120 | def p_and_expr_listing(p): 121 | '''and_expr_listing : shift_expr 122 | | shift_expr "&" and_expr_listing''' 123 | 124 | return 125 | 126 | def p_shift_expr(p): 127 | '''shift_expr : arith_expr 128 | | shift_expr OP_LEFT_SHIFT arith_expr 129 | | shift_expr OP_RIGHT_SHIFT arith_expr''' 130 | 131 | return 132 | 133 | def p_arith_expr(p): 134 | '''arith_expr : term 135 | | arith_expr "+" term 136 | | arith_expr "-" term''' 137 | 138 | return 139 | 140 | def p_term(p): 141 | '''term : term "*" factor 142 | | term "/" factor 143 | | term "%" factor 144 | | term OP_EXACT_DIVISION factor 145 | | factor ''' 146 | 147 | return 148 | 149 | def p_factor(p): 150 | '''factor : "+" factor 151 | | "-" factor 152 | | "~" factor 153 | | power''' 154 | 155 | return 156 | 157 | def p_power(p): 158 | '''power : atom 159 | | atom trailers 160 | | atom OP_POWER factor 161 | | atom trailers OP_POWER factor''' 162 | 163 | return 164 | 165 | def p_trailers(p): 166 | '''trailers : trailers trailer 167 | | trailer''' 168 | 169 | return 170 | 171 | def p_trailer(p): 172 | '''trailer : "(" ")" 173 | | "(" arglist ")" 174 | | "[" subscriptlist "]" 175 | | "." NAME''' 176 | 177 | def p_arglist_piece(p): 178 | '''arglist_piece : argument 179 | | arglist_piece "," argument''' 180 | 181 | return 182 | 183 | 184 | def p_arglist(p): 185 | '''arglist : arglist_piece 186 | | arglist_piece ","''' 187 | 188 | return 189 | 190 | def p_argument(p): 191 | '''argument : test 192 | | test comp_for 193 | | test "=" test''' 194 | return 195 | 196 | def p_subscriptlist(p): 197 | '''subscriptlist : subscriptlist "," subscript 198 | | subscriptlist "," 199 | | subscript''' 200 | 201 | return 202 | 203 | def p_subscript(p): 204 | '''subscript : "." "." "." 205 | | test 206 | | ":" 207 | | test ":" 208 | | ":" test 209 | | test ":" test 210 | | ":" sliceop 211 | | test ":" sliceop 212 | | ":" test sliceop 213 | | test ":" test sliceop''' 214 | 215 | return 216 | 217 | def p_sliceop(p): 218 | '''sliceop : ":" 219 | | ":" test''' 220 | 221 | return 222 | 223 | def p_atom(p): 224 | '''atom : "(" ")" 225 | | "(" yield_expr ")" 226 | | "(" testlist_comp ")" 227 | | "[" "]" 228 | | "[" listmaker "]" 229 | | "{" "}" 230 | | "{" dictorsetmaker "}" 231 | | "`" testlist1 "`" 232 | | NAME 233 | | INTEGER 234 | | FLOAT''' 235 | 236 | return 237 | 238 | def p_testlist1(p): 239 | '''testlist1 : test 240 | | testlist1 "," test''' 241 | 242 | return 243 | 244 | def p_listmaker(p): 245 | '''listmaker : testlist 246 | | test list_for''' 247 | 248 | return 249 | 250 | def p_dsmaker_piece(p): 251 | '''dsmaker_piece : test ":" test 252 | | test 253 | | dsmaker_piece "," test ":" test 254 | | dsmaker_piece "," test''' 255 | 256 | return 257 | 258 | def p_dictorsetmaker(p): 259 | '''dictorsetmaker : dsmaker_piece 260 | | dsmaker_piece "," 261 | | test ":" test comp_for 262 | | test comp_for 263 | ''' 264 | return 265 | 266 | def p_testlist_comp(p): 267 | '''testlist_comp : testlist 268 | | test comp_for''' 269 | 270 | return 271 | 272 | 273 | def p_comp_iter(p): 274 | '''comp_iter : comp_for 275 | | comp_if''' 276 | 277 | def p_comp_for(p): 278 | '''comp_for : TAG_FOR exprlist TAG_IN or_test 279 | | TAG_FOR exprlist TAG_IN or_test comp_iter''' 280 | 281 | return 282 | 283 | def p_comp_if(p): 284 | '''comp_if : TAG_IF old_test 285 | | TAG_IF old_test comp_iter''' 286 | 287 | return 288 | 289 | def p_list_iter(p): 290 | '''list_iter : list_for 291 | | list_if''' 292 | 293 | return 294 | 295 | def p_list_for(p): 296 | '''list_for : TAG_FOR exprlist TAG_IN testlist_safe 297 | | TAG_FOR exprlist TAG_IN testlist_safe list_iter''' 298 | return 299 | 300 | def p_list_if(p): 301 | '''list_if : TAG_IF old_test 302 | | TAG_IF old_test list_iter''' 303 | 304 | return 305 | 306 | def p_testlist(p): 307 | '''testlist : testlist_anns 308 | | testlist_anns ","''' 309 | 310 | return 311 | 312 | def p_testlist_anns(p): 313 | '''testlist_anns : testlist_anns "," test 314 | | test''' 315 | 316 | return 317 | 318 | def p_test(p): 319 | '''test : or_test 320 | | or_test TAG_IF or_test TAG_ELSE test 321 | | lambdef''' 322 | return 323 | 324 | def p_or_test(p): 325 | '''or_test : and_test 326 | | or_test TAG_OR and_test''' 327 | 328 | return 329 | 330 | def p_and_test(p): 331 | '''and_test : not_test 332 | | and_test TAG_AND not_test''' 333 | 334 | return 335 | 336 | def p_not_test(p): 337 | '''not_test : TAG_NOT not_test 338 | | comparison''' 339 | 340 | return 341 | 342 | 343 | def p_comparison(p): 344 | '''comparison : expr 345 | | comparison comp_op expr''' 346 | 347 | print 'find a comparison', p[0], p[1] 348 | 349 | return 350 | 351 | def p_comp_op(p): 352 | '''comp_op : ">" 353 | | "<" 354 | | OP_EQ 355 | | OP_GE 356 | | OP_LE 357 | | OP_NE 358 | | OP_NNE 359 | | TAG_IN 360 | | TAG_NOT TAG_IN 361 | | TAG_IS 362 | | TAG_IS TAG_NOT''' 363 | return 364 | 365 | def p_lambdef(p): 366 | '''lambdef : TAG_LAMBDA ":" test 367 | | TAG_LAMBDA varagslist ":" test''' 368 | 369 | return 370 | 371 | 372 | def p_varagslist(p): 373 | '''varagslist : NAME''' 374 | return 375 | 376 | 377 | def p_fpdef(p): 378 | '''fpdef : NAME 379 | | "(" fplist ")"''' 380 | 381 | return 382 | 383 | def p_fplist_pc(p): 384 | '''fplist_pc : fpdef 385 | | fplist_pc "," fpdef''' 386 | 387 | return 388 | 389 | def p_fplist(p): 390 | '''fplist : fplist_pc 391 | | fplist_pc ","''' 392 | 393 | return 394 | 395 | 396 | def p_funcdef(p): 397 | '''funcdef : TAG_DEF NAME parameters ":" suite''' 398 | return 399 | 400 | def p_parameters(p): 401 | '''parameters : "(" ")" 402 | | "(" varagslist ")"''' 403 | 404 | return 405 | 406 | def p_suite(p): 407 | '''suite : simple_stmt 408 | | NEWLINE INDENT stmts DEDENT''' 409 | 410 | return 411 | 412 | def p_testlist_safe_piece(p): 413 | '''testlist_safe_piece : old_test 414 | | testlist_safe_piece "," old_test''' 415 | 416 | return 417 | 418 | def p_testlist_safe(p): 419 | '''testlist_safe : testlist_safe_piece 420 | | testlist_safe_piece ","''' 421 | 422 | return 423 | 424 | def p_old_test(p): 425 | '''old_test : or_test 426 | | old_lambdef''' 427 | 428 | return 429 | 430 | def p_old_lambdef(p): 431 | '''old_lambdef : TAG_LAMBDA ":" old_test 432 | | TAG_LAMBDA varagslist ":" old_test''' 433 | 434 | return 435 | 436 | def p_stmts(p): 437 | '''stmts : stmt 438 | | stmts stmt''' 439 | 440 | return 441 | 442 | def p_stmt(p): 443 | '''stmt : simple_stmt 444 | | compound_stmt''' 445 | 446 | return 447 | 448 | def p_compound_stmt(p): 449 | '''compound_stmt : if_stmt 450 | | while_stmt 451 | | for_stmt 452 | | funcdef 453 | | classdef''' 454 | 455 | return 456 | 457 | def p_if_stmt(p): 458 | '''if_stmt : TAG_IF test ":" suite 459 | | TAG_IF test ":" suite TAG_ELSE ":" suite 460 | | TAG_IF test ":" suite elif_list 461 | | TAG_IF test ":" suite elif_list TAG_ELSE ":" suite''' 462 | 463 | return 464 | 465 | def p_while_stmt(p): 466 | '''while_stmt : TAG_WHILE test ":" suite 467 | | TAG_WHILE test ":" suite TAG_ELSE ":" suite''' 468 | 469 | return 470 | 471 | def p_for_stmt(p): 472 | '''for_stmt : TAG_FOR exprlist TAG_IN testlist ":" suite 473 | | TAG_FOR exprlist TAG_IN testlist ":" suite TAG_ELSE ":" suite''' 474 | 475 | return 476 | 477 | def p_elif_list(p): 478 | '''elif_list : TAG_ELIF test ":" suite 479 | | elif_list TAG_ELIF test ":" suite''' 480 | 481 | return 482 | 483 | def p_simple_stmt(p): 484 | '''simple_stmt : simple_stmt ";" small_stmt NEWLINE 485 | | simple_stmt ";" small_stmt ";" NEWLINE 486 | | small_stmt NEWLINE 487 | | small_stmt ";" NEWLINE''' 488 | 489 | return 490 | 491 | def p_small_stmt(p): 492 | '''small_stmt : expr_stmt 493 | | print_stmt 494 | | del_stmt 495 | | pass_stmt 496 | | flow_stmt 497 | | import_stmt 498 | | global_stmt 499 | | exec_stmt 500 | | assert_stmt''' 501 | 502 | return 503 | 504 | def p_expr_stmt(p): 505 | '''expr_stmt : testlist''' 506 | 507 | print 'GOT expression' 508 | return 509 | 510 | def p_print_stmt(p): 511 | '''print_stmt : TAG_PRINT 512 | | TAG_PRINT testlist''' 513 | 514 | print 'Waring : got a print' 515 | return 516 | 517 | def p_del_stmt(p): 518 | '''del_stmt : TAG_DEL exprlist''' 519 | 520 | return 521 | 522 | def p_pass_stmt(p): 523 | '''pass_stmt : TAG_PASS''' 524 | 525 | return 526 | 527 | def p_flow_stmt(p): 528 | '''flow_stmt : break_stmt 529 | | continue_stmt 530 | | return_stmt 531 | | raise_stmt 532 | | yield_stmt''' 533 | 534 | return 535 | 536 | def p_break_stmt(p): 537 | '''break_stmt : TAG_BREAK''' 538 | 539 | return 540 | 541 | def p_continue_stmt(p): 542 | '''continue_stmt : TAG_CONTINUE''' 543 | 544 | return 545 | 546 | def p_return_stmt(p): 547 | '''return_stmt : TAG_RETURN 548 | | TAG_RETURN testlist''' 549 | 550 | return 551 | 552 | def p_raise_stmt(p): 553 | '''raise_stmt : TAG_RAISE 554 | | TAG_RAISE test 555 | | TAG_RAISE test "," test 556 | | TAG_RAISE test "," test "," test''' 557 | 558 | return 559 | 560 | def p_import_stmt(p): 561 | '''import_stmt : import_name 562 | | import_from''' 563 | 564 | return 565 | 566 | def p_import_name(p): 567 | '''import_name : TAG_IMPORT dotted_as_names''' 568 | 569 | return 570 | 571 | def p_import_from(p): 572 | '''import_from : TAG_FROM dotted_name TAG_IMPORT "*" 573 | | TAG_FROM dotted_name TAG_IMPORT import_as_names''' 574 | return 575 | 576 | def p_import_as_name(p): 577 | '''import_as_name : NAME 578 | | NAME TAG_AS NAME''' 579 | 580 | return 581 | 582 | def p_dotted_as_name(p): 583 | '''dotted_as_name : dotted_name 584 | | dotted_name TAG_AS NAME''' 585 | return 586 | 587 | def p_import_as_names(p): 588 | '''import_as_names : import_as_names import_as_name 589 | | import_as_name 590 | | import_as_name "," 591 | | import_as_names import_as_name ","''' 592 | 593 | return 594 | 595 | def p_dotted_as_names(p): 596 | '''dotted_as_names : dotted_as_names "," dotted_as_name 597 | | dotted_as_name''' 598 | 599 | return 600 | 601 | def p_dotted_name(p): 602 | '''dotted_name : NAME 603 | | dotted_name "." NAME''' 604 | 605 | return 606 | 607 | def p_global_stmt(p): 608 | '''global_stmt : TAG_GLOBAL namelist''' 609 | 610 | def p_namelist(p): 611 | '''namelist : NAME 612 | | namelist "," NAME''' 613 | 614 | return 615 | 616 | def p_yield_stmt(p): 617 | '''yield_stmt : yield_expr''' 618 | 619 | return 620 | 621 | def p_exec_stmt(p): 622 | '''exec_stmt : TAG_EXEC expr 623 | | TAG_EXEC expr TAG_IN test 624 | | TAG_EXEC expr TAG_IN test "," test''' 625 | 626 | return 627 | 628 | def p_assert_stmt(p): 629 | '''assert_stmt : TAG_ASSERT test 630 | | TAG_ASSERT test "," test''' 631 | 632 | return 633 | 634 | def p_yield_expr(p): 635 | '''yield_expr : TAG_YIELD 636 | | TAG_YIELD testlist''' 637 | 638 | return 639 | 640 | def p_error(p): 641 | if p: 642 | print("Syntax error at '%s', lineno: %d, type: %s" % (p.value, p.lineno, p.type)) 643 | else: 644 | print("Syntax error at EOF") 645 | 646 | 647 | 648 | 649 | import pylex 650 | import yacc 651 | yacc.PY_FLAG = True 652 | yacc.yacc() 653 | 654 | def run(fileName): 655 | try: 656 | f = open(fileName) 657 | except EOFError, IOError: 658 | pass 659 | if f: 660 | yacc.parse('', lexer = pylex.PyLexer(f)) 661 | f.close() 662 | 663 | 664 | if __name__ == "__main__": 665 | if len(sys.argv) < 2: 666 | print 'Usage:', sys.argv[0], 'fileName' 667 | sys.exit(0) 668 | 669 | else: 670 | run(sys.argv[1]) 671 | -------------------------------------------------------------------------------- /src/main/python/rgparser/rg/drawCircle.rg: -------------------------------------------------------------------------------- 1 | c = circle(100, 100, 50, rgb(0, 86, 163)); 2 | c1 = circle(200, 200, 50, rgb(78, 78, 78)); 3 | 4 | l = [c, c1]; 5 | 6 | speedX = 2; 7 | speedY = 3; 8 | 9 | def update() { 10 | global speedX, speedY; 11 | if (c.x + speedX < 100 or c.x + speedX > 800) { 12 | speedX = -speedX; 13 | } 14 | 15 | c.x += speedX; 16 | 17 | if (c.y + speedY < 100 or c.y + speedY > 600) { 18 | speedY = -speedY; 19 | } 20 | 21 | c.y += speedY; 22 | 23 | draw l; 24 | } 25 | 26 | setUpdate(update); -------------------------------------------------------------------------------- /src/main/python/rgparser/rg/drawFlag.rg: -------------------------------------------------------------------------------- 1 | r1 = rect(100, 100, 180, 400, rgb(239, 65, 53)); 2 | r2 = rect(280, 100, 198, 400, rgb(255, 255, 255)); 3 | r3 = rect(478, 100, 222, 400, rgb(0, 85, 164)); 4 | 5 | l = [r1, r2, r3]; 6 | 7 | def flag() { 8 | draw l; 9 | } 10 | 11 | setUpdate(flag); -------------------------------------------------------------------------------- /src/main/python/rgparser/rg/drawText.rg: -------------------------------------------------------------------------------- 1 | t = rgtext("Hello World!", 100, 100, "Arial Black", 36); 2 | c = circle(300, 300, 200, rgb(0, 0, 255)); 3 | 4 | def update() { 5 | draw [t, c]; 6 | } 7 | 8 | setUpdate(update); -------------------------------------------------------------------------------- /src/main/python/rgparser/rg/easySnake.rg: -------------------------------------------------------------------------------- 1 | DIR_RIGHT = 0; 2 | DIR_LEFT = 1; 3 | DIR_UP = 2; 4 | DIR_DOWN = 3; 5 | 6 | FRAME_COUNT = 30; 7 | TIMER_INTERVAL = 3; 8 | 9 | lattice_width = 20; 10 | lattice_height = 20; 11 | 12 | board = roundrect(10, 10, 480, 480, 5, 5); 13 | 14 | padding = 1; 15 | 16 | direction = DIR_DOWN; 17 | 18 | snake = [[120, 100], [100, 100], [80, 100], [60, 100], [40, 100]]; 19 | 20 | food = [120, 140]; 21 | 22 | def update() { 23 | i = 0; 24 | while (i < snake.length()) { 25 | x = snake[i][0] + padding; 26 | y = snake[i][1] + padding; 27 | r = rect(x, y, lattice_width - padding * 2, lattice_height - padding * 2, rgb(65, 65, 65)); 28 | draw r; 29 | i += 1; 30 | } 31 | 32 | x = food[0] + padding; 33 | y = food[1] + padding; 34 | r = rect(x, y, lattice_width - padding * 2, lattice_height - padding * 2, rgb(186, 65, 65)); 35 | draw r; 36 | draw board; 37 | } 38 | 39 | def touchFood(head) { 40 | return ((head[0] == food[0]) and (head[1] == food[1])); 41 | } 42 | 43 | def onTimer() { 44 | if (direction == DIR_RIGHT) { 45 | head = [snake[0][0] + lattice_width, snake[0][1]]; 46 | } 47 | elif (direction == DIR_DOWN) { 48 | head = [snake[0][0], snake[0][1] + lattice_height]; 49 | } 50 | elif (direction == DIR_LEFT) { 51 | head = [snake[0][0] - lattice_width, snake[0][1]]; 52 | } 53 | elif (direction == DIR_UP) { 54 | head = [snake[0][0], snake[0][1] - lattice_height]; 55 | } 56 | 57 | if (touchFood(head)) { 58 | snake.addFirst(head); 59 | generateNewFood(); 60 | return; 61 | } 62 | 63 | i = snake.length() - 1; 64 | while (i > 0) { 65 | snake[i] = snake[i - 1]; 66 | i -= 1; 67 | } 68 | 69 | if (isGameOver(head)) { 70 | gameOver(); 71 | } 72 | 73 | snake[0] = head; 74 | } 75 | 76 | 77 | def onLeft() { 78 | global direction; 79 | if (direction != DIR_RIGHT) { 80 | direction = DIR_LEFT; 81 | } 82 | } 83 | 84 | def onRight() { 85 | global direction; 86 | if (direction != DIR_LEFT) { 87 | direction = DIR_RIGHT; 88 | } 89 | } 90 | 91 | def onUp() { 92 | global direction; 93 | if (direction != DIR_DOWN) { 94 | direction = DIR_UP; 95 | } 96 | } 97 | 98 | def onDown() { 99 | global direction; 100 | if (direction != DIR_UP) { 101 | direction = DIR_DOWN; 102 | } 103 | } 104 | 105 | def restart() { 106 | global direction, snake, food; 107 | 108 | direction = DIR_DOWN; 109 | snake = [[120, 100], [100, 100], [80, 100], [60, 100], [40, 100]]; 110 | food = [120, 140]; 111 | 112 | global c; 113 | c = addTimer(TIMER_INTERVAL, onTimer, True); 114 | } 115 | 116 | setKeyMap({ 117 | "VK_LEFT" : onLeft, 118 | "VK_RIGHT" : onRight, 119 | "VK_UP" : onUp, 120 | "VK_DOWN" : onDown, 121 | "VK_SPACE" : restart, 122 | }); 123 | 124 | def generateNewFood() { 125 | x = random(23) + 1; 126 | y = random(23) + 1; 127 | 128 | while (isOnSnake(x * 20, y * 20)) { 129 | x = random(23) + 1; 130 | y = random(23) + 1; 131 | } 132 | 133 | global food; 134 | food = [x * 20, y * 20]; 135 | } 136 | 137 | def isOnSnake(x, y) { 138 | i = snake.length() - 1; 139 | while (i >= 0) { 140 | if (snake[i][0] == x and snake[i][1] == y) { 141 | return True; 142 | } 143 | i -= 1; 144 | } 145 | 146 | return False; 147 | } 148 | 149 | def isGameOver(head) { 150 | if (head[0] <= 0 or head[0] >= 480 or head[1] <= 0 or head[1] >= 480) { 151 | return True; 152 | } 153 | 154 | return isOnSnake(head[0], head[1]); 155 | } 156 | 157 | def gameOver() { 158 | global c; 159 | c.stop(); 160 | } 161 | 162 | setFrameCount(FRAME_COUNT); 163 | c = addTimer(TIMER_INTERVAL, onTimer, True); 164 | setUpdate(update); -------------------------------------------------------------------------------- /src/main/python/rgparser/rg/eight_number.rg: -------------------------------------------------------------------------------- 1 | r = roundrect(175, 75, 450, 450, 10, 10); 2 | line1 = line(325, 75, 325, 525); 3 | line2 = line(175, 225, 625, 225); 4 | line3 = line(475, 75, 475, 525); 5 | line4 = line(175, 375, 625, 375); 6 | 7 | board = [r, line1, line2, line3, line4]; 8 | 9 | l = [2, 1, 0, 3, 4, 2, 5, 8, 6, 7]; 10 | 11 | def move(dir) { 12 | if (dir == 1 and l[0] % 3 == 0) { 13 | return; 14 | } 15 | 16 | if (dir == -1 and l[0] % 3 == 1) { 17 | return; 18 | } 19 | 20 | if (l[0] + dir < 1 or l[0] + dir > 9) { 21 | return; 22 | } 23 | 24 | l[l[0]] = l[l[0] + dir]; 25 | l[0] = l[0] + dir; 26 | l[l[0]] = 0; 27 | } 28 | 29 | setKeyMap({ 30 | "VK_LEFT" : (lambda : move(1)), 31 | "VK_RIGHT" : (lambda : move(-1)), 32 | "VK_UP" : (lambda : move(3)), 33 | "VK_DOWN" : (lambda : move(-3)), 34 | }); 35 | 36 | def isWin() { 37 | i = 0; 38 | while (i< 8) { 39 | i += 1; 40 | if (l[i] != i) { 41 | return False; 42 | } 43 | } 44 | 45 | return l[9] == 0; 46 | } 47 | 48 | def update() { 49 | i = 1; 50 | 51 | if (not isWin()) { 52 | while (i <= 9) { 53 | if (l[i] == 0) { 54 | i += 1; 55 | continue; 56 | } 57 | 58 | x = 250 + (i + 2) % 3 * 150 - 12; 59 | y = 150 + (i - 1) / 3 * 150 + 12; 60 | t = rgtext(l[i], x, y, "Arial Black", 24); 61 | 62 | draw t; 63 | i += 1; 64 | } 65 | draw board; 66 | } 67 | else { 68 | t = rgtext("You Win", 312, 262, "Arial Black", 24); 69 | draw t; 70 | } 71 | } 72 | 73 | setUpdate(update); 74 | -------------------------------------------------------------------------------- /src/main/python/rgparser/rg/lambda.rg: -------------------------------------------------------------------------------- 1 | g = (lambda : "hello world"); 2 | f = (lambda x : 2 * x ); 3 | -------------------------------------------------------------------------------- /src/main/python/rgparser/rg/renju.rg: -------------------------------------------------------------------------------- 1 | OFFSET_X = 220; 2 | OFFSET_Y = 50; 3 | LATTICE_WIDTH = 37; 4 | CHESS_RADIUS = 15; 5 | 6 | FRAME_COUNTE = 3; 7 | 8 | EMPTY = 0; 9 | BLACK = 1; 10 | WHITE = 2; 11 | 12 | board = []; 13 | turn = BLACK; 14 | 15 | # initialize the chess board 16 | i = 0; 17 | while (i < 15) { 18 | l = []; 19 | j = 0; 20 | while (j < 15) { 21 | l.addFirst(EMPTY); 22 | j += 1; 23 | } 24 | 25 | board.addFirst(l); 26 | i += 1; 27 | } 28 | 29 | def restart() { 30 | i = 0; 31 | while (i < 15) { 32 | j = 0; 33 | while (j < 15) { 34 | board[i][j] = EMPTY; 35 | j += 1; 36 | } 37 | i += 1; 38 | } 39 | } 40 | 41 | def update() { 42 | i = 0; 43 | while (i < 15) { 44 | x = OFFSET_X + i * LATTICE_WIDTH; 45 | draw line(x, OFFSET_Y, x, OFFSET_Y + 14 * LATTICE_WIDTH); 46 | i += 1; 47 | } 48 | 49 | i = 0; 50 | while (i < 15) { 51 | y = OFFSET_Y + i * LATTICE_WIDTH; 52 | draw line(OFFSET_X, y, OFFSET_X + 14 * LATTICE_WIDTH, y); 53 | i += 1; 54 | } 55 | 56 | i = 0; 57 | while (i < 15) { 58 | j = 0; 59 | while (j < 15) { 60 | if (board[i][j] == BLACK) { 61 | draw circle(OFFSET_X + LATTICE_WIDTH * j - CHESS_RADIUS, OFFSET_Y + LATTICE_WIDTH * i - CHESS_RADIUS, CHESS_RADIUS * 2, rgb(55, 55, 55)); 62 | } 63 | elif (board[i][j] == WHITE) { 64 | draw circle(OFFSET_X + LATTICE_WIDTH * j - CHESS_RADIUS, OFFSET_Y + LATTICE_WIDTH * i - CHESS_RADIUS, CHESS_RADIUS * 2, rgb(128, 128, 255)); 65 | } 66 | j += 1; 67 | } 68 | i += 1; 69 | } 70 | } 71 | 72 | def addChess(x, y) { 73 | global turn; 74 | line = (x - OFFSET_X + LATTICE_WIDTH / 2) / LATTICE_WIDTH; 75 | row = (y - OFFSET_Y + LATTICE_WIDTH / 2) / LATTICE_WIDTH; 76 | 77 | if (board[row][line] == EMPTY) { 78 | board[row][line] = turn; 79 | turn = 3 - turn; 80 | } 81 | } 82 | 83 | setMouseMap({ 84 | "LEFT_CLICK" : addChess, 85 | }); 86 | 87 | setKeyMap({ 88 | "VK_SPACE" : restart, 89 | }); 90 | 91 | setFrameCount(FRAME_COUNTE); 92 | setUpdate(update); -------------------------------------------------------------------------------- /src/main/python/rgparser/rg/snake.rg: -------------------------------------------------------------------------------- 1 | DIR_RIGHT = 0; 2 | DIR_LEFT = 1; 3 | DIR_UP = 2; 4 | DIR_DOWN = 3; 5 | 6 | FRAME_COUNT = 30; 7 | TIMER_INTERVAL = 3; 8 | 9 | lattice_width = 20; 10 | lattice_height = 20; 11 | 12 | board = roundrect(10, 10, 480, 480, 5, 5); 13 | 14 | padding = 1; 15 | 16 | direction = DIR_DOWN; 17 | 18 | snake = [[120, 100], [100, 100], [80, 100], [60, 100], [40, 100]]; 19 | 20 | food = [120, 140]; 21 | 22 | def update() { 23 | i = 0; 24 | while (i < snake.length()) { 25 | x = snake[i][0] + padding; 26 | y = snake[i][1] + padding; 27 | r = rect(x, y, lattice_width - padding * 2, lattice_height - padding * 2, rgb(65, 65, 65)); 28 | draw r; 29 | i += 1; 30 | } 31 | 32 | x = food[0] + padding; 33 | y = food[1] + padding; 34 | r = rect(x, y, lattice_width - padding * 2, lattice_height - padding * 2, rgb(186, 65, 65)); 35 | draw r; 36 | draw board; 37 | } 38 | 39 | def touchFood(head) { 40 | return ((head[0] == food[0]) and (head[1] == food[1])); 41 | } 42 | 43 | def onTimer() { 44 | if (direction == DIR_RIGHT) { 45 | head = [snake[0][0] + lattice_width, snake[0][1]]; 46 | } 47 | elif (direction == DIR_DOWN) { 48 | head = [snake[0][0], snake[0][1] + lattice_height]; 49 | } 50 | elif (direction == DIR_LEFT) { 51 | head = [snake[0][0] - lattice_width, snake[0][1]]; 52 | } 53 | elif (direction == DIR_UP) { 54 | head = [snake[0][0], snake[0][1] - lattice_height]; 55 | } 56 | 57 | if (touchFood(head)) { 58 | snake.addFirst(head); 59 | generateNewFood(); 60 | return; 61 | } 62 | 63 | i = snake.length() - 1; 64 | while (i > 0) { 65 | snake[i] = snake[i - 1]; 66 | i -= 1; 67 | } 68 | 69 | if (isGameOver(head)) { 70 | gameOver(); 71 | } 72 | 73 | snake[0] = head; 74 | } 75 | 76 | 77 | def onLeft() { 78 | global direction; 79 | if (direction != DIR_RIGHT) { 80 | direction = DIR_LEFT; 81 | } 82 | } 83 | 84 | def onRight() { 85 | global direction; 86 | if (direction != DIR_LEFT) { 87 | direction = DIR_RIGHT; 88 | } 89 | } 90 | 91 | def onUp() { 92 | global direction; 93 | if (direction != DIR_DOWN) { 94 | direction = DIR_UP; 95 | } 96 | } 97 | 98 | def onDown() { 99 | global direction; 100 | if (direction != DIR_UP) { 101 | direction = DIR_DOWN; 102 | } 103 | } 104 | 105 | def restart() { 106 | global direction, snake, food; 107 | 108 | direction = DIR_DOWN; 109 | snake = [[120, 100], [100, 100], [80, 100], [60, 100], [40, 100]]; 110 | food = [120, 140]; 111 | 112 | global c; 113 | c = addTimer(TIMER_INTERVAL, onTimer, True); 114 | } 115 | 116 | setKeyMap({ 117 | "VK_LEFT" : onLeft, 118 | "VK_RIGHT" : onRight, 119 | "VK_UP" : onUp, 120 | "VK_DOWN" : onDown, 121 | "VK_SPACE" : restart, 122 | }); 123 | 124 | def generateNewFood() { 125 | x = random(23) + 1; 126 | y = random(23) + 1; 127 | 128 | while (isOnSnake(x * 20, y * 20)) { 129 | x = random(23) + 1; 130 | y = random(23) + 1; 131 | } 132 | 133 | global food; 134 | food = [x * 20, y * 20]; 135 | } 136 | 137 | def isOnSnake(x, y) { 138 | i = snake.length() - 1; 139 | while (i >= 0) { 140 | if (snake[i][0] == x and snake[i][1] == y) { 141 | return True; 142 | } 143 | i -= 1; 144 | } 145 | 146 | return False; 147 | } 148 | 149 | def isGameOver(head) { 150 | if (head[0] <= 0 or head[0] >= 480 or head[1] <= 0 or head[1] >= 480) { 151 | return True; 152 | } 153 | 154 | return isOnSnake(head[0], head[1]); 155 | } 156 | 157 | def gameOver() { 158 | global c; 159 | c.stop(); 160 | } 161 | 162 | setFrameCount(FRAME_COUNT); 163 | c = addTimer(TIMER_INTERVAL, onTimer, True); 164 | setUpdate(update); -------------------------------------------------------------------------------- /src/main/python/rgparser/rg/test3d.rg: -------------------------------------------------------------------------------- 1 | c = camera(); 2 | 3 | global posZ; 4 | posZ = 0; 5 | 6 | def update() { 7 | #global posZ; 8 | #posZ += 1; 9 | #c.setTranslateZ(posZ); 10 | } -------------------------------------------------------------------------------- /src/main/python/rgparser/rg/testClass.rg: -------------------------------------------------------------------------------- 1 | class A() { 2 | a = 1; 3 | 4 | def f() { 5 | return "hello"; 6 | } 7 | } 8 | 9 | x = A(); 10 | draw x.a; 11 | x.b = 2; 12 | draw x.b; -------------------------------------------------------------------------------- /src/main/python/rgparser/rg/testMouse.rg: -------------------------------------------------------------------------------- 1 | global c; 2 | 3 | def drawCircle(x, y) { 4 | global c; 5 | c = circle(x, y, random(30), rgb(86, 0, 164)); 6 | } 7 | 8 | def dragMouse(x, y) { 9 | c.x = x; 10 | c.y = y; 11 | } 12 | 13 | setMouseMap({ 14 | "LEFT_CLICK" : drawCircle, 15 | "DRAG" : dragMouse, 16 | }); 17 | 18 | def update() { 19 | draw c; 20 | } 21 | 22 | setUpdate(update); -------------------------------------------------------------------------------- /src/main/python/rgparser/show.py: -------------------------------------------------------------------------------- 1 | import dis, marshal, struct, sys, time, types 2 | 3 | def show_file(fname): 4 | f = open(fname, "rb") 5 | magic = f.read(4) 6 | moddate = f.read(4) 7 | # modtime = time.asctime(time.localtime(struct.unpack('L', moddate)[0])) 8 | print "magic %s" % (magic.encode('hex')) 9 | print "moddate %s" % (moddate.encode('hex')) 10 | code = marshal.load(f) 11 | show_code(code) 12 | 13 | def show_code(code, indent=''): 14 | old_indent = indent 15 | print "%s" % indent 16 | indent += ' ' 17 | print "%s %d " % (indent, code.co_argcount) 18 | print "%s %d" % (indent, code.co_nlocals) 19 | print "%s %d" % (indent, code.co_stacksize) 20 | print "%s %04x" % (indent, code.co_flags) 21 | show_hex("code", code.co_code, indent=indent) 22 | print "%s" % indent 23 | dis.disassemble(code) 24 | print "%s" % indent 25 | 26 | print "%s %r" % (indent, code.co_names) 27 | print "%s %r" % (indent, code.co_varnames) 28 | print "%s %r" % (indent, code.co_freevars) 29 | print "%s %r" % (indent, code.co_cellvars) 30 | print "%s %r" % (indent, code.co_filename) 31 | print "%s %r" % (indent, code.co_name) 32 | print "%s %d" % (indent, code.co_firstlineno) 33 | 34 | print "%s" % indent 35 | for const in code.co_consts: 36 | if type(const) == types.CodeType: 37 | show_code(const, indent+' ') 38 | else: 39 | print " %s%r" % (indent, const) 40 | print "%s" % indent 41 | 42 | show_hex("lnotab", code.co_lnotab, indent=indent) 43 | print "%s" % old_indent 44 | 45 | def show_hex(label, h, indent): 46 | h = h.encode('hex') 47 | if len(h) < 60: 48 | print "%s<%s> %s" % (indent, label, h,label) 49 | else: 50 | print "%s<%s>" % (indent, label) 51 | for i in range(0, len(h), 60): 52 | print "%s %s" % (indent, h[i:i+60]) 53 | print "%s" % (indent, label) 54 | 55 | show_file(sys.argv[1]) 56 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/Assem.py: -------------------------------------------------------------------------------- 1 | #-*- coding: UTF-8 -*- 2 | # 3 | # ----------------------------------------------------------------------------- 4 | # bytecode generators for python 5 | # author : gzxuwei@corp.netease.com 6 | # date : 2015-08-14 7 | # ----------------------------------------------------------------------------- 8 | 9 | import const 10 | import dis 11 | import types 12 | 13 | RAW = "RAW" 14 | FLAT = "FLAT" 15 | CONV = "CONV" 16 | DONE = "DONE" 17 | 18 | class FlowGraph(object): 19 | def __init__(self): 20 | super(FlowGraph, self).__init__() 21 | self.current = self.entry = Block() 22 | self.exit = Block("exit") 23 | self.blocks = set() 24 | self.blocks.add(self.entry) 25 | self.blocks.add(self.exit) 26 | 27 | self._debug = False 28 | 29 | return 30 | 31 | def start_block(self, block): 32 | if self._debug: 33 | if self.current: 34 | print "end", repr(self.current) 35 | print " next", self.current.next 36 | print " preve", self.current.prev 37 | print " ", self.current.get_children() 38 | print repr(block) 39 | 40 | self.current = block 41 | 42 | return 43 | 44 | def next_block(self, block = None): 45 | if block is None: 46 | block = self.new_block() 47 | 48 | self.current.add_next(block) 49 | self.start_block(block) 50 | 51 | return 52 | 53 | def new_block(self): 54 | b = Block() 55 | self.blocks.add(b) 56 | return b 57 | 58 | def start_exit_block(self): 59 | self.start_block(self.exit) 60 | return 61 | 62 | def _enable_debug(self): 63 | self._debug = True 64 | 65 | return 66 | 67 | def _disable_debug(self): 68 | self._debug = False 69 | 70 | return 71 | 72 | def emit(self, *inst): 73 | if len(inst) == 2 and isinstance(inst[1], Block): 74 | self.current.add_out_edge(inst[1]) 75 | 76 | self.current.emit(inst) 77 | 78 | return 79 | 80 | def get_blocks_inorder(self): 81 | return self.order_blocks() 82 | 83 | def get_blocks(self): 84 | return list(self.blocks) 85 | 86 | def get_root(self): 87 | return self.entry 88 | 89 | def get_contained_graphs(self): 90 | l = [] 91 | for b in self.get_blocks(): 92 | l.extend(b.get_contained_graphs()) 93 | 94 | return l 95 | 96 | def order_blocks(self): 97 | order = [] 98 | remaining = set() 99 | todo = [self.entry] 100 | 101 | while todo: 102 | b = todo.pop() 103 | if b in remaining: 104 | continue 105 | 106 | remaining.add(b) 107 | 108 | for c in b.get_children(): 109 | if c not in remaining: 110 | todo.append(c) 111 | 112 | dominators = {} 113 | for b in remaining: 114 | dominators.setdefault(b, set()) 115 | 116 | for c in b.get_followers(): 117 | while True: 118 | dominators.setdefault(c, set()).add(b) 119 | 120 | if c.prev and c.prev[0] is not b: 121 | c = c.prev[0] 122 | else: 123 | break 124 | 125 | def find_next(): 126 | for b in remaining: 127 | for c in dominators[b]: 128 | if c in remaining: 129 | break 130 | else: 131 | return b 132 | 133 | assert 0, 'circular dependency, cannot find next block' 134 | 135 | b = self.entry 136 | 137 | while True: 138 | order.append(b) 139 | remaining.discard(b) 140 | 141 | if b.next: 142 | b = b.next[0] 143 | continue 144 | 145 | elif b is not self.exit and not b.has_unconditional_transfer(): 146 | order.append(self.exit) 147 | 148 | if not remaining: 149 | break 150 | 151 | b = find_next() 152 | 153 | return order 154 | 155 | class PyFlowGraph(FlowGraph): 156 | hasjrel = set() 157 | for i in dis.hasjrel: 158 | hasjrel.add(dis.opname[i]) 159 | hasjabs = set() 160 | for i in dis.hasjabs: 161 | hasjabs.add(dis.opname[i]) 162 | 163 | def __init__(self, name, filename, optimized = 0, args = (), klass = None, function_block = False): 164 | super(PyFlowGraph, self).__init__() 165 | self.name = name 166 | self.filename = filename 167 | self.docstring = None 168 | self.args = args 169 | self.argcount = len(args) 170 | self.klass = klass 171 | self.optimized = optimized 172 | self.function_block = function_block 173 | 174 | if optimized: 175 | self.flags = const.CO_OPTIMIZED | const.CO_NEWLOCALS 176 | else: 177 | self.flags = 0 178 | 179 | self.consts = [] 180 | self.names = [] 181 | self.freevars = [] 182 | self.cellvars = [] 183 | self.closure = [] 184 | self.varnames = [] 185 | self.stage = RAW 186 | 187 | return 188 | 189 | def set_doc_string(self, doc): 190 | self.docstring = doc 191 | 192 | return 193 | 194 | def set_flag(self, flag): 195 | self.flags = self.flags | flag 196 | if flag == const.CO_VARARGS: 197 | self.argcount = self.argcount - 1 198 | 199 | return 200 | 201 | def check_flag(self, flag): 202 | if self.flag & flag: 203 | return 1 204 | 205 | def set_free_vars(self, names): 206 | self.freevars = list(names) 207 | 208 | return 209 | 210 | def set_cell_vars(self, names): 211 | self.cellvars = names 212 | 213 | return 214 | 215 | def finish(self, is_lambda): 216 | self.start_exit_block() 217 | if not is_lambda: 218 | self.emit("LOAD_CONST", None) 219 | self.emit("RETURN_VALUE") 220 | 221 | return 222 | 223 | def get_code(self): 224 | assert self.stage == RAW 225 | self.compute_stack_depth() 226 | self.flatten_graph() 227 | assert self.stage == FLAT 228 | self.convert_args() 229 | assert self.stage == CONV 230 | self.make_byte_code() 231 | assert self.stage == DONE 232 | return self.new_code_object() 233 | 234 | def compute_stack_depth(self): 235 | depth = {} 236 | exit = None 237 | 238 | for b in self.get_blocks(): 239 | depth[b] = find_depth(b.get_instructions()) 240 | 241 | seen = {} 242 | 243 | def max_depth(b, d): 244 | if b in seen: 245 | return d 246 | seen[b] = 1 247 | d = d + depth[b] 248 | children = b.get_children() 249 | 250 | if children: 251 | return max([max_depth(c, d) for c in children]) 252 | 253 | else: 254 | if not b.label == "exit": 255 | return max_depth(self.exit, d) 256 | else: 257 | return d 258 | 259 | self.stacksize = max_depth(self.entry, 0) 260 | 261 | return 262 | 263 | def flatten_graph(self): 264 | assert self.stage == RAW 265 | self.insts = insts = [] 266 | pc = 0 267 | begin = {} 268 | end = {} 269 | 270 | for b in self.get_blocks_inorder(): 271 | begin[b] = pc 272 | for inst in b.get_instructions(): 273 | insts.append(inst) 274 | 275 | if len(inst) == 1: 276 | pc += 1 277 | elif inst[0] != "SET_LINENO": 278 | pc += 3 279 | 280 | end[b] = pc 281 | pc = 0 282 | 283 | for i in range(len(insts)): 284 | inst = insts[i] 285 | if len(inst) == 1: 286 | pc = pc + 1 287 | 288 | elif inst[0] != "SET_LINENO": 289 | pc += 3 290 | 291 | opname = inst[0] 292 | if opname in self.hasjrel: 293 | oparg = inst[1] 294 | offset = begin[oparg] - pc 295 | insts[i] = opname, offset 296 | 297 | elif opname in self.hasjabs: 298 | insts[i] = opname, begin[inst[1]] 299 | 300 | self.stage = FLAT 301 | 302 | return 303 | 304 | def convert_args(self): 305 | assert self.stage == FLAT 306 | self.consts.insert(0, self.docstring) 307 | self.sort_cellvars() 308 | 309 | for i in range(len(self.insts)): 310 | t = self.insts[i] 311 | 312 | if len(t) == 2: 313 | opname, oparg = t 314 | conv_func = self._converters.get(opname, None) 315 | 316 | if conv_func: 317 | self.insts[i] = opname, conv_func(self, oparg) 318 | 319 | self.stage = CONV 320 | 321 | return 322 | 323 | def sort_cellvars(self): 324 | cells = {} 325 | for name in self.cellvars: 326 | cells[name] = 1 327 | 328 | self.cellvars = [name for name in self.varnames if name in cells] 329 | 330 | for name in self.cellvars: 331 | del cells[name] 332 | 333 | self.cellvars = self.cellvars + cells.keys() 334 | self.closure = self.cellvars + self.freevars 335 | 336 | return 337 | 338 | def _lookup_name(self, name, l): 339 | t = type(name) 340 | for index, item in enumerate(l): 341 | if t == type(item) and item == name: 342 | return index 343 | 344 | end = len(l) 345 | l.append(name) 346 | return end 347 | 348 | _converters = {} 349 | def _convert_LOAD_CONST(self, arg): 350 | if hasattr(arg, 'get_code'): 351 | arg = arg.get_code() 352 | 353 | return self._lookup_name(arg, self.consts) 354 | 355 | def _convert_LOAD_FAST(self, arg): 356 | self._lookup_name(arg, self.names) 357 | return self._lookup_name(arg, self.varnames) 358 | 359 | _convert_STORE_FAST = _convert_LOAD_FAST 360 | _convert_DELETE_FAST = _convert_LOAD_FAST 361 | 362 | def _convert_LOAD_NAME(self, arg): 363 | if self.klass is None: 364 | self._lookup_name(arg, self.varnames) 365 | return self._lookup_name(arg, self.names) 366 | 367 | _convert_STORE_NAME = _convert_LOAD_NAME 368 | _convert_DELETE_NAME = _convert_LOAD_NAME 369 | _convert_IMPORT_NAME = _convert_LOAD_NAME 370 | _convert_IMPORT_FROM = _convert_LOAD_NAME 371 | _convert_STORE_ATTR = _convert_LOAD_NAME 372 | _convert_LOAD_ATTR = _convert_LOAD_NAME 373 | _convert_DELETE_ATTR = _convert_LOAD_NAME 374 | _convert_LOAD_GLOBAL = _convert_LOAD_NAME 375 | _convert_STORE_GLOBAL = _convert_LOAD_NAME 376 | _convert_DELETE_GLOBAL = _convert_LOAD_NAME 377 | 378 | def _convert_DEREF(self, arg): 379 | self._lookup_name(arg, self.names) 380 | self._lookup_name(arg, self.varnames) 381 | return self._lookup_name(arg, self.closure) 382 | 383 | _convert_LOAD_DEREF = _convert_DEREF 384 | _convert_STORE_DEREF = _convert_DEREF 385 | 386 | def _convert_LOAD_CLOSURE(self, arg): 387 | self._lookup_name(arg, self.varnames) 388 | return self._lookup_name(arg, self.closure) 389 | 390 | _cmp = list(dis.cmp_op) 391 | def _convert_COMPARE_OP(self, arg): 392 | return self._cmp.index(arg) 393 | 394 | for name, obj in locals().items(): 395 | if name[:9] == "_convert_": 396 | opname = name[9:] 397 | _converters[opname] = obj 398 | 399 | del name, obj, opname 400 | 401 | opnum = {} 402 | for num in range(len(dis.opname)): 403 | opnum[dis.opname[num]] = num 404 | del num 405 | 406 | def make_byte_code(self): 407 | assert self.stage == CONV 408 | self.lnotab = lnotab = LineNumberTable() 409 | 410 | for t in self.insts: 411 | opname = t[0] 412 | if len(t) == 1: 413 | lnotab.add_code(self.opnum[opname]) 414 | 415 | else: 416 | oparg = t[1] 417 | 418 | if opname == "SET_LINENO": 419 | lnotab.next_line(oparg) 420 | continue 421 | 422 | hi, lo = twobyte(oparg) 423 | 424 | try: 425 | lnotab.add_code(self.opnum[opname], lo, hi) 426 | except ValueError: 427 | print opname, oparg 428 | print self.opnum[opname], lo, hi 429 | raise 430 | 431 | self.stage = DONE 432 | 433 | def new_code_object(self): 434 | assert self.stage == DONE 435 | 436 | if (self.flags & const.CO_NEWLOCALS) == 0: 437 | nlocals = 0 438 | else: 439 | nlocals = len(self.varnames) 440 | 441 | argcount = self.argcount 442 | 443 | return types.CodeType(argcount, nlocals, self.stacksize, self.flags, 444 | self.lnotab.get_code(), self.get_consts(), 445 | tuple(self.names), tuple(self.varnames), 446 | self.filename, self.name, self.lnotab.firstline, 447 | self.lnotab.get_table(), tuple(self.freevars), 448 | tuple(self.cellvars)) 449 | 450 | def get_consts(self): 451 | l = [] 452 | for elt in self.consts: 453 | if isinstance(elt, PyFlowGraph): 454 | elt = elt.get_code() 455 | l.append(elt) 456 | 457 | return tuple(l) 458 | 459 | def is_jump(opname): 460 | if opname[:4] == "JUMP": 461 | return 1 462 | 463 | def twobyte(val): 464 | assert isinstance(val, int) 465 | return divmod(val, 256) 466 | 467 | class Block(object): 468 | _count = 0 469 | 470 | def __init__(self, label = ''): 471 | self.insts = [] 472 | self.out_edges = set() 473 | self.label = label 474 | self.bid = Block._count 475 | self.next = [] 476 | self.prev = [] 477 | Block._count = Block._count + 1 478 | 479 | def __repr__(self): 480 | if self.label: 481 | return "" % (self.label, self.bid) 482 | else: 483 | return "" % (self.bid) 484 | 485 | def __str__(self): 486 | insts = map(str, self.insts) 487 | return "" % (self.label, self.bid, '\n'.join(insts)) 488 | 489 | def emit(self, inst): 490 | self.insts.append(inst) 491 | 492 | return 493 | 494 | def get_instructions(self): 495 | return self.insts 496 | 497 | def add_out_edge(self, block): 498 | self.out_edges.add(block) 499 | return 500 | 501 | def add_next(self, block): 502 | self.next.append(block) 503 | block.prev.append(self) 504 | 505 | return 506 | 507 | _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS', 'JUMP_ABSOLUTE', 508 | 'JUMP_FORWARD', 'CONTINUE_LOOP',) 509 | 510 | def has_unconditional_transfer(self): 511 | try: 512 | op, arg = self.insts[-1] 513 | except (IndexError, ValueError): 514 | return 515 | 516 | return op in self._uncond_transfer 517 | 518 | def get_children(self): 519 | return list(self.out_edges) + self.next 520 | 521 | def get_followers(self): 522 | followers = set(self.next) 523 | for inst in self.insts: 524 | if inst[0] in PyFlowGraph.hasjrel: 525 | followers.add(inst[1]) 526 | 527 | return followers 528 | 529 | def get_contained_graphs(self): 530 | contained = [] 531 | 532 | for inst in self.insts: 533 | if len(inst) == 1: 534 | continue 535 | 536 | arg = inst[1] 537 | if hasattr(arg, 'graph'): 538 | contained.append(arg.graph) 539 | 540 | return contained 541 | 542 | class LineNumberTable(object): 543 | def __init__(self): 544 | super(LineNumberTable, self).__init__() 545 | 546 | self.code = [] 547 | self.code_offset = 0 548 | self.firstline = 0 549 | self.lastline = 0 550 | self.lastoff = 0 551 | self.lnotab = [] 552 | 553 | return 554 | 555 | def add_code(self, *args): 556 | for arg in args: 557 | self.code.append(chr(arg)) 558 | 559 | self.code_offset += len(args) 560 | 561 | return 562 | 563 | def next_line(self, lineno): 564 | if self.firstline == 0: 565 | self.firstline = lineno 566 | self.lastline = lineno 567 | 568 | else: 569 | addr = self.code_offset - self.lastoff 570 | line = lineno - self.lastline 571 | 572 | if line >= 0: 573 | push = self.lnotab.append 574 | while addr > 255: 575 | push(255) 576 | push(0) 577 | addr -= 255 578 | 579 | while line > 255: 580 | push(addr) 581 | push(255) 582 | line -= 255 583 | addr = 0 584 | 585 | if addr > 0 or line > 0: 586 | push(addr) 587 | push(line) 588 | 589 | self.lastline = lineno 590 | self.lastoff = self.code_offset 591 | 592 | return 593 | 594 | def get_code(self): 595 | return ''.join(self.code) 596 | 597 | def get_table(self): 598 | return ''.join(map(chr, self.lnotab)) 599 | 600 | class StackDepthTracker: 601 | # XXX 1. need to keep track of stack depth on jumps 602 | # XXX 2. at least partly as a result, this code is broken 603 | 604 | def find_depth(self, insts, debug=0): 605 | depth = 0 606 | maxDepth = 0 607 | for i in insts: 608 | opname = i[0] 609 | delta = self.effect.get(opname, None) 610 | if delta is not None: 611 | depth = depth + delta 612 | else: 613 | # now check patterns 614 | for pat, pat_delta in self.patterns: 615 | if opname[:len(pat)] == pat: 616 | delta = pat_delta 617 | depth = depth + delta 618 | break 619 | # if we still haven't found a match 620 | if delta is None: 621 | meth = getattr(self, opname, None) 622 | if meth is not None: 623 | depth = depth + meth(i[1]) 624 | if depth > maxDepth: 625 | maxDepth = depth 626 | return maxDepth 627 | 628 | effect = { 629 | 'POP_TOP': -1, 630 | 'DUP_TOP': 1, 631 | 'LIST_APPEND': -1, 632 | 'SET_ADD': -1, 633 | 'MAP_ADD': -2, 634 | 'SLICE+1': -1, 635 | 'SLICE+2': -1, 636 | 'SLICE+3': -2, 637 | 'STORE_SLICE+0': -1, 638 | 'STORE_SLICE+1': -2, 639 | 'STORE_SLICE+2': -2, 640 | 'STORE_SLICE+3': -3, 641 | 'DELETE_SLICE+0': -1, 642 | 'DELETE_SLICE+1': -2, 643 | 'DELETE_SLICE+2': -2, 644 | 'DELETE_SLICE+3': -3, 645 | 'STORE_SUBSCR': -3, 646 | 'DELETE_SUBSCR': -2, 647 | # PRINT_EXPR? 648 | 'PRINT_ITEM': -1, 649 | 'RETURN_VALUE': -1, 650 | 'YIELD_VALUE': -1, 651 | 'EXEC_STMT': -3, 652 | 'BUILD_CLASS': -2, 653 | 'STORE_NAME': -1, 654 | 'STORE_ATTR': -2, 655 | 'DELETE_ATTR': -1, 656 | 'STORE_GLOBAL': -1, 657 | 'BUILD_MAP': 1, 658 | 'COMPARE_OP': -1, 659 | 'STORE_FAST': -1, 660 | 'IMPORT_STAR': -1, 661 | 'IMPORT_NAME': -1, 662 | 'IMPORT_FROM': 1, 663 | 'LOAD_ATTR': 0, # unlike other loads 664 | # close enough... 665 | 'SETUP_EXCEPT': 3, 666 | 'SETUP_FINALLY': 3, 667 | 'FOR_ITER': 1, 668 | 'WITH_CLEANUP': -1, 669 | } 670 | 671 | # use pattern match 672 | patterns = [ 673 | ('BINARY_', -1), 674 | ('LOAD_', 1), 675 | ] 676 | 677 | def UNPACK_SEQUENCE(self, count): 678 | return count-1 679 | 680 | def BUILD_TUPLE(self, count): 681 | return -count+1 682 | 683 | def BUILD_LIST(self, count): 684 | return -count+1 685 | 686 | def BUILD_SET(self, count): 687 | return -count+1 688 | 689 | def CALL_FUNCTION(self, argc): 690 | hi, lo = divmod(argc, 256) 691 | return -(lo + hi * 2) 692 | 693 | def CALL_FUNCTION_VAR(self, argc): 694 | return self.CALL_FUNCTION(argc)-1 695 | 696 | def CALL_FUNCTION_KW(self, argc): 697 | return self.CALL_FUNCTION(argc)-1 698 | 699 | def CALL_FUNCTION_VAR_KW(self, argc): 700 | return self.CALL_FUNCTION(argc)-2 701 | 702 | def MAKE_FUNCTION(self, argc): 703 | return -argc 704 | 705 | def MAKE_CLOSURE(self, argc): 706 | # XXX need to account for free variables too! 707 | return -argc 708 | 709 | def BUILD_SLICE(self, argc): 710 | if argc == 2: 711 | return -1 712 | elif argc == 3: 713 | return -2 714 | 715 | def DUP_TOPX(self, argc): 716 | return argc 717 | 718 | find_depth = StackDepthTracker().find_depth 719 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/Scope.py: -------------------------------------------------------------------------------- 1 | #-*- coding: UTF-8 -*- 2 | 3 | from const import * 4 | 5 | class Scope(object): 6 | def __init__(self, name, module, klass = None): 7 | self.name = name 8 | self.module = module 9 | self.defs = {} 10 | self.uses = {} 11 | self.globals = {} 12 | self.params = {} 13 | self.frees = {} 14 | self.cells = {} 15 | self.children = [] 16 | 17 | self.nested = None 18 | self.generator = None 19 | self.klass = None 20 | 21 | if klass is not None: 22 | for i in range(len(klass)): 23 | if klass[i] != '_': 24 | self.klass = klass[i:] 25 | break 26 | 27 | def __repr__(self): 28 | return "<%s: %s>" % (self.__class__.__name__, self.name) 29 | 30 | def mangle(self, name): 31 | return name 32 | 33 | def add_def(self, name): 34 | self.defs[self.mangle(name)] = 1 35 | 36 | return 37 | 38 | def add_use(self, name): 39 | self.uses[self.mangle(name)] = 1 40 | 41 | return 42 | 43 | def add_global(self, name): 44 | name = self.mangle(name) 45 | 46 | # 局部变量覆盖全局变量 ? 47 | if name in self.uses or name in self.defs: 48 | pass 49 | 50 | if name in self.params: 51 | raise SyntaxError, "%s in %s in globals and parameters" % (name, self.name) 52 | 53 | self.globals[name] = 1 54 | self.module.add_def(name) 55 | 56 | return 57 | 58 | def add_param(self, name): 59 | name = self.mangle(name) 60 | self.defs[name] = 1 61 | self.params[name] = 1 62 | 63 | return 64 | 65 | def get_names(self): 66 | d = {} 67 | d.update(self.defs) 68 | d.update(self.uses) 69 | d.update(self.globals) 70 | 71 | return d.keys() 72 | 73 | def add_child(self, child): 74 | self.children.append(child) 75 | 76 | return 77 | 78 | def get_children(self): 79 | return self.children 80 | 81 | def check_name(self, name): 82 | if name in self.globals: 83 | return SC_GLOBAL_EXPLICIT 84 | 85 | if name in self.cells: 86 | return SC_CELL 87 | 88 | if name in self.defs: 89 | return SC_LOCAL 90 | 91 | if self.nested and (name in self.frees or name in self.uses): 92 | return SC_FREE 93 | 94 | if self.nested: 95 | return SC_UNKNOWN 96 | 97 | else: 98 | return SC_GLOBAL_IMPLICIT 99 | 100 | def get_free_vars(self): 101 | if not self.nested: 102 | return () 103 | 104 | free = {} 105 | free.update(self.frees) 106 | 107 | # 这里使用了自由变量的定义去计算,但上面的self.frees又是什么鬼 108 | for name in self.uses.keys(): 109 | if name not in self.defs and name not in self.globals: 110 | free[name] = 1 111 | 112 | return free.keys() 113 | 114 | def handle_children(self): 115 | for child in self.children: 116 | frees = child.get_free_vars() 117 | globals = self.add_frees(frees) 118 | for name in globals: 119 | child.force_global(name) 120 | 121 | return 122 | 123 | # 当前结点的某些子结点有可能把一个name当成free ref,这是因为 124 | # 在处理这些子结点的时候,它的 enclosing scope 没有被处理。现在 125 | # es处理完了,再回过头来处理子结点。 126 | def force_global(self, name): 127 | self.globals[name] = 1 128 | if name in self.frees: 129 | del self.frees[name] 130 | 131 | for child in self.children: 132 | if child.check_name(name) == SC_FREE: 133 | child.force_global(name) 134 | 135 | return 136 | 137 | # 处理嵌套作用域里的自由变量 138 | def add_frees(self, names): 139 | child_globals = [] 140 | 141 | for name in names: 142 | sc = self.check_name(name) 143 | 144 | if self.nested: 145 | if sc == SC_UNKNOWN or sc == SC_FREE or isinstance(self, ClassScope): 146 | self.frees[name] = 1 147 | 148 | elif sc == SC_GLOBAL_IMPLICIT: 149 | child_globals.append(name) 150 | 151 | elif isinstance(self, FunctionScope) and sc == SC_LOCAL: 152 | self.cells[name] = 1 153 | 154 | elif sc != SC_CELL: 155 | child_globals.append(name) 156 | 157 | else: 158 | if sc == SC_LOCAL: 159 | self.cells[name] = 1 160 | 161 | elif sc != SC_CELL: 162 | child_globals.append(name) 163 | 164 | return child_globals 165 | 166 | def get_cell_vars(self): 167 | return self.cells.keys() 168 | 169 | def debug(self): 170 | print "===========" 171 | print "name is", self.name 172 | if self.nested: 173 | print "nested" 174 | print "defs is", self.defs 175 | print "params is", self.params 176 | print "cells is", self.cells 177 | print "frees is", self.frees 178 | print "global is", self.globals 179 | print "use is", self.uses 180 | 181 | return 182 | 183 | class ModuleScope(Scope): 184 | def __init__(self): 185 | super(ModuleScope, self).__init__("global", self) 186 | 187 | class FunctionScope(Scope): 188 | pass 189 | 190 | class ClassScope(Scope): 191 | def __init__(self, name, module): 192 | super(ClassScope, self).__init__(name, module) 193 | 194 | class CompScope(Scope): 195 | def __init__(self, name, module, klass = None): 196 | super(CompScope, self).__init__(name, module, klass) 197 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/SymtableVisitor.py: -------------------------------------------------------------------------------- 1 | #-*- coding: UTF-8 -*- 2 | 3 | import ast 4 | from Scope import * 5 | 6 | class SymtableVisitor(object): 7 | def __init__(self): 8 | super(SymtableVisitor, self).__init__() 9 | self.scopes = {} 10 | self.module = None 11 | self.klass = None 12 | 13 | return 14 | 15 | def is_type(self, node, type_name): 16 | return node.__class__.__name__ == type_name 17 | 18 | def visit(self, node, parent): 19 | klass = node.__class__.__name__ 20 | 21 | func = getattr(self, 'visit_%s' % klass, None) 22 | 23 | if func: 24 | func(node, parent) 25 | 26 | return 27 | 28 | def visit_ClassDef(self, node, parent): 29 | for deco in node.decorator_list: 30 | self.visit(deco, parent) 31 | 32 | for base in node.bases: 33 | self.visit(base, parent) 34 | 35 | parent.add_def(node.name) 36 | scope = ClassScope(node.name, self.module) 37 | 38 | if parent.nested or isinstance(parent, FunctionScope): 39 | scope.nested = 1 40 | 41 | scope.add_def('__module__') 42 | self.scopes[node] = scope 43 | prev = self.klass 44 | self.klass = node.name 45 | 46 | for stmt in node.body: 47 | self.visit(stmt, scope) 48 | 49 | self.klass = prev 50 | self.handle_free_vars(scope, parent) 51 | 52 | scope.debug() 53 | 54 | return 55 | 56 | def visit_FunctionDef(self, node, parent): 57 | if node.decorator_list: 58 | self.visit(node.decorator_list, parent) 59 | 60 | for default in node.args.defaults: 61 | self.visit(default, parent) 62 | 63 | parent.add_def(node.name) 64 | scope = FunctionScope(node.name, self.module, self.klass) 65 | 66 | if parent.nested or isinstance(parent, FunctionScope): 67 | scope.nested = 1 68 | 69 | self.scopes[node] = scope 70 | self.visit(node.args, scope) 71 | 72 | for stmt in node.body: 73 | self.visit(stmt, scope) 74 | 75 | self.handle_free_vars(scope, parent) 76 | 77 | scope.debug() 78 | 79 | return 80 | 81 | def visit_Module(self, node, parent): 82 | scope = self.module = self.scopes[node] = ModuleScope() 83 | for stmt in node.body: 84 | self.visit(stmt, scope) 85 | 86 | scope.debug() 87 | return 88 | 89 | def visit_Return(self, node, parent): 90 | self.visit(node.value, parent) 91 | 92 | return 93 | 94 | def visit_Delete(self, node, parent): 95 | for tgt in node.targets: 96 | self.visit(tgt, parent) 97 | 98 | return 99 | 100 | def visit_Name(self, node, parent): 101 | if self.is_type(node.ctx, "Store"): 102 | parent.add_def(node.id) 103 | else: 104 | parent.add_use(node.id) 105 | 106 | return 107 | 108 | def visit_Global(self, node, parent): 109 | for name in node.names: 110 | parent.add_global(name) 111 | 112 | return 113 | 114 | def visit_Print(self, node, parent): 115 | if node.dest: 116 | self.visit(node.dest, parent) 117 | 118 | for v in node.values: 119 | self.visit(v, parent) 120 | 121 | return 122 | 123 | def visit_For(self, node, parent): 124 | self.visit(node.target, parent) 125 | self.visit(node.iter, parent) 126 | 127 | for stmt in node.body: 128 | self.visit(stmt, parent) 129 | 130 | for stmt in node.orelse: 131 | self.visit(stmt, parent) 132 | 133 | return 134 | 135 | def visit_While(self, node, parent): 136 | self.visit(node.test, parent) 137 | 138 | for stmt in node.body: 139 | self.visit(stmt, parent) 140 | 141 | for stmt in node.orelse: 142 | self.visit(stmt, parent) 143 | 144 | return 145 | 146 | def visit_If(self, node, parent): 147 | self.visit(node.test, parent) 148 | 149 | for stmt in node.body: 150 | self.visit(stmt, parent) 151 | 152 | for stmt in node.orelse: 153 | self.visit(stmt, parent) 154 | 155 | return 156 | 157 | def visit_Raise(self, node, parent): 158 | if node.type: 159 | self.visit(node.type, parent) 160 | 161 | if node.inst: 162 | self.visit(node.inst, parent) 163 | 164 | if node.tback: 165 | self.visit(node.tback, parent) 166 | return 167 | 168 | def visit_TryExcept(self, node, parent): 169 | 170 | return 171 | 172 | def visit_Expr(self, node, parent): 173 | self.visit(node.value, parent) 174 | 175 | return 176 | 177 | def visit_With(self, node, parent): 178 | self.visit(node.context_expr, parent) 179 | 180 | if node.optional_vars: 181 | self.visit(node.optional_vars, parent) 182 | 183 | for stmt in node.body: 184 | self.visit(stmt, parent) 185 | 186 | return 187 | 188 | def visit_Import(self, node, parent): 189 | pass 190 | 191 | def visit_Assign(self, node, parent): 192 | for target in node.targets: 193 | self.visit(target, parent) 194 | 195 | self.visit(node.value, parent) 196 | 197 | return 198 | 199 | def visit_Call(self, node, parent): 200 | self.visit(node.func, parent) 201 | 202 | for arg in node.args: 203 | self.visit(arg, parent) 204 | 205 | for keyword in node.keywords: 206 | self.visit(keyword, parent) 207 | 208 | if node.starargs: 209 | self.visit(node.starargs, parent) 210 | 211 | if node.kwargs: 212 | self.visit(node.kwargs, parent) 213 | 214 | return 215 | 216 | # 217 | # expressions 218 | # 219 | def visit_BoolOp(self, node, parent): 220 | for v in node.values: 221 | self.visit(v, parent) 222 | 223 | return 224 | 225 | def visit_BinOp(self, node, parent): 226 | self.visit(node.left, parent) 227 | self.visit(node.right, parent) 228 | 229 | return 230 | 231 | def visit_Tuple(self, node, parent): 232 | for name in node.elts: 233 | self.visit(name, parent) 234 | 235 | return 236 | 237 | def visit_ListComp(self, node, parent): 238 | self.visit(node.elt, parent) 239 | 240 | for comp in node.generators: 241 | self.visit_comprehension(comp, parent) 242 | 243 | return 244 | 245 | def visit_DictComp(self, node, parent): 246 | self.handle_comprehension("", node, node.key, node.value, parent) 247 | 248 | return 249 | 250 | def visit_SetComp(self, node, parent): 251 | self.handle_comprehension("", node, node.elt, None, parent) 252 | 253 | return 254 | 255 | def visit_GeneratorExp(self, node, parent): 256 | self.handle_comprehension("", node, node.elt, None, parent) 257 | 258 | return 259 | 260 | def visit_arguments(self, node, parent): 261 | self.do_args(node.args, parent) 262 | 263 | if node.vararg: 264 | parent.add_param(node.vararg) 265 | 266 | if node.kwarg: 267 | parent.add_param(node.kwarg) 268 | 269 | return 270 | 271 | def do_args(self, args, parent): 272 | for arg in args: 273 | if arg.__class__.__name__ == "Tuple": 274 | self.do_args(arg.elts, parent) 275 | else: 276 | parent.add_param(arg.id) 277 | 278 | return 279 | 280 | def visit_comprehension(self, node, parent): 281 | self.visit(node.target, parent) 282 | self.visit(node.iter, parent) 283 | 284 | for if_stmt in node.ifs: 285 | self.visit(if_stmt, parent) 286 | 287 | return 288 | 289 | def handle_free_vars(self, scope, parent): 290 | parent.add_child(scope) 291 | scope.handle_children() 292 | 293 | return 294 | 295 | def handle_comprehension(self, scope_name, node, elt, value, parent): 296 | outermost = node.generators[0] 297 | 298 | self.visit(outermost.iter, parent) 299 | 300 | scope = CompScope(scope_name, self.module, self.klass) 301 | if parent.nested or isinstance(parent, FunctionScope) or isinstance(parent, CompScope): 302 | scope.nested = 1 303 | self.scopes[node] = scope 304 | 305 | self.visit(outermost.target, scope) 306 | self.visit(outermost.ifs, scope) 307 | 308 | for comp in node.generators[1:]: 309 | self.visit(comp, scope) 310 | 311 | if value: 312 | self.visit(value, scope) 313 | self.visit(elt, scope) 314 | 315 | self.handle_free_vars(scope, parent) 316 | scope.debug() 317 | 318 | return 319 | 320 | def visit_Lambda(self, node, parent): 321 | for default in node.args.defaults: 322 | self.visit(default, parent) 323 | 324 | scope = FunctionScope("", self.module, self.klass) 325 | 326 | if parent.nested or isinstance(parent, FunctionScope): 327 | scope.nested = 1 328 | 329 | self.scopes[node] = scope 330 | self.visit(node.args, scope) 331 | 332 | self.visit(node.body, scope) 333 | 334 | self.handle_free_vars(scope, parent) 335 | 336 | scope.debug() 337 | 338 | return 339 | 340 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/const.py: -------------------------------------------------------------------------------- 1 | #-*- coding: UTF-8 -*- 2 | # 3 | # ----------------------------------------------------------------------------- 4 | # This file is copied from Lib/compiler/consts.py 5 | # author : gzxuwei@corp.netease.com 6 | # date : 2015-08-15 7 | # ----------------------------------------------------------------------------- 8 | 9 | # operation flags 10 | OP_ASSIGN = 'OP_ASSIGN' 11 | OP_DELETE = 'OP_DELETE' 12 | OP_APPLY = 'OP_APPLY' 13 | 14 | SC_LOCAL = 1 15 | SC_GLOBAL_IMPLICIT = 2 16 | SC_GLOBAL_EXPLICIT = 3 17 | SC_FREE = 4 18 | SC_CELL = 5 19 | SC_UNKNOWN = 6 20 | 21 | CO_OPTIMIZED = 0x0001 22 | CO_NEWLOCALS = 0x0002 23 | CO_VARARGS = 0x0004 24 | CO_VARKEYWORDS = 0x0008 25 | CO_NESTED = 0x0010 26 | CO_GENERATOR = 0x0020 27 | CO_GENERATOR_ALLOWED = 0 28 | CO_FUTURE_DIVISION = 0x2000 29 | CO_FUTURE_ABSIMPORT = 0x4000 30 | CO_FUTURE_WITH_STATEMENT = 0x8000 31 | CO_FUTURE_PRINT_FUNCTION = 0x10000 32 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/testfiles/test_assign_print.ldd: -------------------------------------------------------------------------------- 1 | i = 1 2 | a, b = (3, 4) 3 | print i, 2, (a, b) 4 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/testfiles/test_class.ldd: -------------------------------------------------------------------------------- 1 | class TestObject(object): 2 | def __init__(self): 3 | self.a = 1 4 | self.b = 2 5 | print "in constructor" 6 | 7 | def sayHello(self): 8 | self.a += 1 9 | self.b += self.a 10 | print "hello", self.a, self.b 11 | 12 | a = TestObject() 13 | a.sayHello() 14 | a.sayHello() 15 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/testfiles/test_comp.ldd: -------------------------------------------------------------------------------- 1 | s = [x for x in range(3, 10) if x % 2] 2 | 3 | for i in s: 4 | print i 5 | 6 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/testfiles/test_control.ldd: -------------------------------------------------------------------------------- 1 | i = 0 2 | while i < 10: 3 | i = i + 1 4 | 5 | if i == 5: 6 | break 7 | else: 8 | print i 9 | 10 | else: 11 | print 'not found' 12 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/testfiles/test_datas.ldd: -------------------------------------------------------------------------------- 1 | #l = [(x, y) for x in range(10) if x % 2 == 0 for y in range(x)] 2 | #print l 3 | 4 | #a = 1 5 | #b = 2 6 | #del a, b 7 | # 8 | 9 | #from traceback import print_stack as ps 10 | #ps() 11 | 12 | from sys import * 13 | print flags 14 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/testfiles/test_func.ldd: -------------------------------------------------------------------------------- 1 | #def f((a, (b, c)) = (3, (4, 5))): 2 | # t = a 3 | # print t 4 | # return t 5 | 6 | #i = 1 7 | #def get_func(): 8 | # t = 3 9 | # def func(): 10 | # print i, t 11 | # 12 | # return func 13 | # 14 | #f = get_func() 15 | #n = f() 16 | 17 | l = [] 18 | 19 | def get_f(): 20 | for i in range(10): 21 | #f = lambda a, b = i: a + b 22 | f = lambda a: a + i 23 | 24 | l.append(f) 25 | 26 | 27 | get_f() 28 | for f in l: 29 | print f(1) 30 | 31 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/testfiles/test_if.ldd: -------------------------------------------------------------------------------- 1 | a = 1 2 | b = 2 3 | c = 3 4 | d = 4 5 | 6 | if a < b and c < d: 7 | print "true" 8 | else: 9 | print "false" 10 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/testfiles/test_stmt.ldd: -------------------------------------------------------------------------------- 1 | co = compile("print a, b", "", "exec") 2 | exec co in {'a' : 1}, {'b' : 2} 3 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/testfiles/test_subscr.ldd: -------------------------------------------------------------------------------- 1 | #a[0:-1] 2 | #a[:] 3 | #a[::-1] 4 | #a[1,2] 5 | a[(1,2),::,...,5] += 2 6 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/testfiles/test_try.ldd: -------------------------------------------------------------------------------- 1 | #raise SyntaxError, "hahaha" 2 | # 3 | #try: 4 | # print 1 5 | # 6 | #except ZeroDivisionError, e: 7 | # print "find an z error" 8 | # 9 | #except NameError, ne: 10 | # print "find an a error" 11 | # 12 | #else: 13 | # print "no error" 14 | 15 | assert True 16 | assert False 17 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/testfiles/test_with.ldd: -------------------------------------------------------------------------------- 1 | with open("testfiles/test_class.ldd") as f: 2 | for line in f: 3 | print line 4 | -------------------------------------------------------------------------------- /src/main/python/rgparser/symtable/unit_test.py: -------------------------------------------------------------------------------- 1 | import SymtableVisitor as SV 2 | import CodeGen 3 | import ast 4 | 5 | def test_file(fname): 6 | pass 7 | 8 | def test_flowgraph(): 9 | import Assem 10 | f = Assem.PyFlowGraph("f", "h.py") 11 | f.emit("LOAD_CONST", 1) 12 | f.emit("PRINT_ITEM") 13 | f.emit("PRINT_NEWLINE") 14 | f.emit("LOAD_CONST", None) 15 | f.emit("RETURN_VALUE") 16 | 17 | g = Assem.PyFlowGraph("r", "h.py") 18 | g.emit("LOAD_CONST", f) 19 | g.emit("MAKE_FUNCTION", 0) 20 | g.emit("STORE_NAME", "func") 21 | g.emit("LOAD_NAME", "func") 22 | g.emit("CALL_FUNCTION", 0) 23 | g.emit("POP_TOP") 24 | g.emit("LOAD_CONST", None) 25 | g.emit("RETURN_VALUE") 26 | 27 | co = g.get_code() 28 | print co.co_consts 29 | import dis 30 | dis.dis(co) 31 | exec co 32 | 33 | return 34 | 35 | 36 | if __name__ == "__main__": 37 | #fname = "testfiles/test_func.ldd" 38 | #fname = "testfiles/test_if.ldd" 39 | #fname = "testfiles/test_control.ldd" 40 | #fname = "testfiles/test_datas.ldd" 41 | #fname = "testfiles/test_try.ldd" 42 | #fname = "testfiles/test_comp.ldd" 43 | #fname = "testfiles/test_class.ldd" 44 | #fname = "testfiles/test_with.ldd" 45 | #fname = "testfiles/test_stmt.ldd" 46 | fname = "testfiles/test_subscr.ldd" 47 | #test_file("testfiles/test_assign_print.ldd") 48 | #test_flowgraph() 49 | 50 | f = open(fname) 51 | s = f.read() 52 | st = ast.parse(s) 53 | 54 | print ast.dump(st) 55 | codeGen = CodeGen.CodeGen(fname) 56 | codeGen.visit(st, None, None) 57 | co = codeGen.get_code() 58 | 59 | import dis 60 | print "=========" 61 | dis.dis(co) 62 | #dis.dis(co.co_consts[2]) 63 | #print "=========" 64 | #dis.dis(co.co_consts[2].co_consts[2]) 65 | #print co.co_consts[2].co_consts[2].co_names 66 | #print co.co_consts[4].co_argcount 67 | 68 | print "=========" 69 | 70 | co = compile(st, "s", "exec") 71 | #print co.co_consts[3].co_varnames 72 | dis.dis(co) 73 | #print "=========" 74 | #dis.dis(co.co_consts[1]) 75 | #dis.dis(co.co_consts[1].co_consts[1]) 76 | #print co.co_consts[1].co_consts[2].co_names 77 | 78 | #exec co 79 | -------------------------------------------------------------------------------- /src/main/python/rgparser/test/test.ddl: -------------------------------------------------------------------------------- 1 | c = circle(100, 100, 50, rgb(0, 86, 163)); 2 | c1 = circle(200, 200, 50, rgb(78, 78, 78)); 3 | 4 | l = [c, c1]; 5 | 6 | speedX = 2; 7 | speedY = 1; 8 | 9 | def update(){ 10 | global speedX, speedY; 11 | if ( speedX < 100 or speedX > 800) 12 | { 13 | draw c; 14 | } 15 | } -------------------------------------------------------------------------------- /src/main/python/rgparser/test/test.hy: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | class A(object): 4 | def testFile(self, filePath): 5 | if os.path.isfile(filePath): 6 | if 1 == 1: 7 | return True 8 | 9 | else: 10 | return False -------------------------------------------------------------------------------- /src/main/python/rgparser/test/test.py: -------------------------------------------------------------------------------- 1 | def foo(): 2 | x = 1 3 | del x 4 | def bar(): 5 | print x 6 | 7 | return bar 8 | 9 | g = foo() 10 | g() 11 | -------------------------------------------------------------------------------- /src/main/python/rgparser/test/test.rgb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinus/railgun/3778549acaf30bade0aab9bdc47380a3a6eb20ad/src/main/python/rgparser/test/test.rgb -------------------------------------------------------------------------------- /src/main/python/rgparser/test/test_class.ddl: -------------------------------------------------------------------------------- 1 | class A(object): 2 | def __init__(self, value): 3 | self.v = value 4 | 5 | def p(self): 6 | print self.v 7 | return 8 | 9 | a = A(1) 10 | a.p() 11 | -------------------------------------------------------------------------------- /src/main/python/rgparser/test/test_dict.ddl: -------------------------------------------------------------------------------- 1 | l = [1, 2, 3] 2 | d = {1:'a', 2:'b', 3:'c'} 3 | 4 | for value in l: 5 | if value in d: 6 | print value, d[value] 7 | 8 | d[1] = 3 9 | print d[1] 10 | -------------------------------------------------------------------------------- /src/main/python/rgparser/test/test_for.ddl: -------------------------------------------------------------------------------- 1 | for a in xrange(5): 2 | if a == 6: 3 | break 4 | 5 | else: 6 | print None 7 | 8 | -------------------------------------------------------------------------------- /src/main/python/rgparser/test/test_func.ddl: -------------------------------------------------------------------------------- 1 | def foo(a, b): 2 | return a + b 3 | 4 | print foo(1, 2) ** 2 5 | -------------------------------------------------------------------------------- /src/main/python/rgparser/test/test_if.ddl: -------------------------------------------------------------------------------- 1 | a = 49.5 2 | if a > 50: 3 | print "Greater" 4 | 5 | elif a == 50: 6 | print r'Equal' "hehe" 7 | 8 | else: 9 | print "Less" "haha" 10 | -------------------------------------------------------------------------------- /src/main/python/rgparser/test/test_import.ddl: -------------------------------------------------------------------------------- 1 | import os as o 2 | from os.path import isdir as d, isfile as f 3 | 4 | if f("D:\\"): 5 | print "File" 6 | elif d("D:\\"): 7 | print "Directory" 8 | else: 9 | print 0 10 | -------------------------------------------------------------------------------- /src/main/python/rgparser/test/test_list.ddl: -------------------------------------------------------------------------------- 1 | def double(x): 2 | return x * 2 3 | 4 | a = [1, 2, 3] 5 | b = map(double, a) 6 | 7 | for index, value in enumerate(b): 8 | print index, value 9 | 10 | -------------------------------------------------------------------------------- /src/main/python/rgparser/test/test_print.ddl: -------------------------------------------------------------------------------- 1 | a, b = i, j = 1, 2 2 | print a, b, i, j 3 | print 3 * (1 + 5) ** 2 4 | -------------------------------------------------------------------------------- /src/main/python/rgparser/test/test_try.ddl: -------------------------------------------------------------------------------- 1 | try: 2 | a = 1 / 0 3 | except: 4 | pass 5 | finally: 6 | pass 7 | 8 | -------------------------------------------------------------------------------- /src/main/python/rgparser/test/test_while.ddl: -------------------------------------------------------------------------------- 1 | i = 1 2 | total = 0 3 | 4 | while i <= 100: 5 | i += 1 6 | total += i 7 | 8 | print total 9 | -------------------------------------------------------------------------------- /src/test/java/LibraryTest.java: -------------------------------------------------------------------------------- 1 | import org.junit.Test; 2 | import static org.junit.Assert.*; 3 | 4 | /* 5 | * This Java source file was auto generated by running 'gradle init --type java-library' 6 | * by 'hinus' at '17-11-30 下午4:13' with Gradle 3.2.1 7 | * 8 | * @author hinus, @date 17-11-30 下午4:13 9 | */ 10 | public class LibraryTest { 11 | @Test public void testSomeLibraryMethod() { 12 | Library classUnderTest = new Library(); 13 | assertTrue("someLibraryMethod should return 'true'", classUnderTest.someLibraryMethod()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/python/drawCircle.py: -------------------------------------------------------------------------------- 1 | c = circle(100, 100, 50, rgb(0, 86, 163)) 2 | c1 = circle(200, 200, 50, rgb(78, 78, 78)) 3 | 4 | l = [c, c1] 5 | 6 | speedX = 2 7 | speedY = 1 8 | 9 | def update(): 10 | global speedX, speedY 11 | if c.x + speedX < 100 or c.x + speedX > 800: 12 | speedX = -speedX 13 | 14 | c.x += speedX 15 | 16 | if c.y + speedY < 100 or c.y + speedY > 600: 17 | speedY = -speedY 18 | 19 | c.y += speedY 20 | 21 | print c, c1 -------------------------------------------------------------------------------- /src/test/python/drawText.py: -------------------------------------------------------------------------------- 1 | t = rgtext("Hello World", 100, 100, "Arial Black", 24) 2 | 3 | def update(): 4 | print t -------------------------------------------------------------------------------- /src/test/python/eight_number.py: -------------------------------------------------------------------------------- 1 | r = roundrect(175, 75, 450, 450, 10, 10) 2 | line1 = line(325, 75, 325, 525) 3 | line2 = line(175, 225, 625, 225) 4 | line3 = line(475, 75, 475, 525) 5 | line4 = line(175, 375, 625, 375) 6 | 7 | board = [r, line1, line2, line3, line4] 8 | 9 | l = [2, 1, 0, 3, 4, 2, 5, 8, 6, 7] 10 | 11 | def move(dir): 12 | if dir == 1 and l[0] % 3 == 0: 13 | return 14 | 15 | if dir == -1 and l[0] % 3 == 1: 16 | return 17 | 18 | if l[0] + dir < 1 or l[0] + dir > 9: 19 | return 20 | 21 | l[l[0]] = l[l[0] + dir] 22 | l[0] = l[0] + dir 23 | l[l[0]] = 0 24 | 25 | def onLeft(): 26 | move(1) 27 | 28 | def onRight(): 29 | move(-1) 30 | 31 | def onUp(): 32 | move(3) 33 | 34 | def onDown(): 35 | move(-3) 36 | 37 | KeyMap = { 38 | "VK_LEFT" : onLeft, 39 | "VK_RIGHT" : onRight, 40 | "VK_UP" : onUp, 41 | "VK_DOWN" : onDown, 42 | } 43 | 44 | def isWin(): 45 | i = 0 46 | while i< 8: 47 | i += 1 48 | if l[i] != i: 49 | return False 50 | return l[9] == 0 51 | 52 | 53 | def update(): 54 | i = 1 55 | 56 | if not isWin(): 57 | while i <= 9: 58 | if l[i] == 0: 59 | i += 1 60 | continue 61 | 62 | x = 250 + (i + 2) % 3 * 150 - 12 63 | y = 150 + (i - 1) / 3 * 150 + 12 64 | t = rgtext(l[i], x, y, "Arial Black", 24) 65 | 66 | print t 67 | i += 1 68 | 69 | print board 70 | else: 71 | t = rgtext("You Win", 312, 262, "Arial Black", 24) 72 | print t 73 | 74 | -------------------------------------------------------------------------------- /src/test/rg/drawFlag.rg: -------------------------------------------------------------------------------- 1 | r1 = rect(100, 100, 180, 400, rgb(239, 65, 53)); 2 | r2 = rect(280, 100, 198, 400, rgb(255, 255, 255)); 3 | r3 = rect(478, 100, 222, 400, rgb(0, 85, 164)); 4 | 5 | l = [r1, r2, r3]; 6 | 7 | draw l; --------------------------------------------------------------------------------