Procházet zdrojové kódy

- Added example project

- Added some utility methods
Stan Hebben před 6 roky
rodič
revize
e9b5ccf146

+ 8
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/partial/PartialMemberGroupExpression.java Zobrazit soubor

@@ -12,6 +12,7 @@ import org.openzen.zenscript.codemodel.FunctionHeader;
12 12
 import org.openzen.zenscript.codemodel.expression.CallArguments;
13 13
 import org.openzen.zenscript.codemodel.expression.Expression;
14 14
 import org.openzen.zenscript.codemodel.expression.LambdaClosure;
15
+import org.openzen.zenscript.codemodel.member.ICallableMember;
15 16
 import org.openzen.zenscript.codemodel.type.member.DefinitionMemberGroup;
16 17
 import org.openzen.zenscript.codemodel.type.GenericName;
17 18
 import org.openzen.zenscript.codemodel.type.ITypeID;
@@ -34,6 +35,13 @@ public class PartialMemberGroupExpression implements IPartialExpression {
34 35
 		this.group = group;
35 36
 		this.allowStaticUsage = allowStaticMembers;
36 37
 	}
38
+	
39
+	public PartialMemberGroupExpression(CodePosition position, Expression target, ICallableMember member, boolean allowStaticMembers) {
40
+		this.position = position;
41
+		this.target = target;
42
+		this.group = DefinitionMemberGroup.forMethod(member);
43
+		this.allowStaticUsage = allowStaticMembers;
44
+	}
37 45
 
38 46
 	@Override
39 47
 	public Expression eval() {

+ 9
- 1
CodeModel/src/main/java/org/openzen/zenscript/codemodel/partial/PartialStaticMemberGroupExpression.java Zobrazit soubor

@@ -10,17 +10,25 @@ import java.util.stream.Collectors;
10 10
 import org.openzen.zenscript.codemodel.FunctionHeader;
11 11
 import org.openzen.zenscript.codemodel.expression.CallArguments;
12 12
 import org.openzen.zenscript.codemodel.expression.Expression;
13
+import org.openzen.zenscript.codemodel.member.ICallableMember;
13 14
 import org.openzen.zenscript.codemodel.type.member.DefinitionMemberGroup;
14 15
 import org.openzen.zenscript.codemodel.type.GenericName;
15 16
 import org.openzen.zenscript.codemodel.type.ITypeID;
16 17
 import org.openzen.zenscript.shared.CodePosition;
17 18
 import org.openzen.zenscript.codemodel.scope.TypeScope;
19
+import org.openzen.zenscript.codemodel.type.member.TypeMemberPriority;
18 20
 
19 21
 /**
20 22
  *
21 23
  * @author Hoofdgebruiker
22 24
  */
23 25
 public class PartialStaticMemberGroupExpression implements IPartialExpression {
26
+	public static PartialStaticMemberGroupExpression forMethod(CodePosition position, ICallableMember method) {
27
+		DefinitionMemberGroup group = new DefinitionMemberGroup();
28
+		group.addMethod(method, TypeMemberPriority.SPECIFIED);
29
+		return new PartialStaticMemberGroupExpression(position, group);
30
+	}
31
+	
24 32
 	private final CodePosition position;
25 33
 	private final DefinitionMemberGroup group;
26 34
 	
@@ -28,7 +36,7 @@ public class PartialStaticMemberGroupExpression implements IPartialExpression {
28 36
 		this.position = position;
29 37
 		this.group = group;
30 38
 	}
31
-
39
+	
32 40
 	@Override
33 41
 	public Expression eval() {
34 42
 		return group.staticGetter(position);

+ 8
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/DefinitionTypeID.java Zobrazit soubor

@@ -20,7 +20,15 @@ import org.openzen.zenscript.codemodel.generic.TypeParameter;
20 20
  * @author Hoofdgebruiker
21 21
  */
22 22
 public class DefinitionTypeID implements ITypeID {
23
+	public static DefinitionTypeID forType(HighLevelDefinition definition) {
24
+		if (!definition.genericParameters.isEmpty())
25
+			throw new IllegalArgumentException("Definition has type arguments!");
26
+		
27
+		return new DefinitionTypeID(definition, NO_TYPE_PARAMETERS);
28
+	}
29
+	
23 30
 	private static final OuterTypeEntry[] NO_OUTER_ENTRIES = new OuterTypeEntry[0];
31
+	private static final ITypeID[] NO_TYPE_PARAMETERS = new ITypeID[0];
24 32
 	
25 33
 	public final HighLevelDefinition definition;
26 34
 	public final ITypeID[] typeParameters;

+ 6
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/DefinitionMemberGroup.java Zobrazit soubor

@@ -35,6 +35,12 @@ import org.openzen.zenscript.codemodel.scope.TypeScope;
35 35
  * @author Hoofdgebruiker
36 36
  */
37 37
 public class DefinitionMemberGroup {
38
+	public static DefinitionMemberGroup forMethod(ICallableMember member) {
39
+		DefinitionMemberGroup instance = new DefinitionMemberGroup();
40
+		instance.addMethod(member, TypeMemberPriority.SPECIFIED);
41
+		return instance;
42
+	}
43
+	
38 44
 	private TypeMember<FieldMember> field;
39 45
 	private TypeMember<IGettableMember> getter;
40 46
 	private TypeMember<SetterMember> setter;

+ 18
- 0
ScriptingExample/build.gradle Zobrazit soubor

@@ -0,0 +1,18 @@
1
+// Note: "common.gradle" in the root project contains additional initialization
2
+//   for this project. This initialization is applied in the "build.gradle"
3
+//   of the root project.
4
+
5
+// NetBeans will automatically add "run" and "debug" tasks relying on the
6
+// "mainClass" property. You may however define the property prior executing
7
+// tasks by passing a "-PmainClass=<QUALIFIED_CLASS_NAME>" argument.
8
+//
9
+// Note however, that you may define your own "run" and "debug" task if you
10
+// prefer. In this case NetBeans will not add these tasks but you may rely on
11
+// your own implementation.
12
+if (!hasProperty('mainClass')) {
13
+    ext.mainClass = 'org.openzen.zenscript.scriptingexample.Main'
14
+}
15
+
16
+dependencies {
17
+	compile project(':Parser')
18
+}

+ 1
- 0
ScriptingExample/scripts/helloworld.zs Zobrazit soubor

@@ -0,0 +1 @@
1
+println("Hello world!");

+ 96
- 0
ScriptingExample/src/main/java/org/openzen/zenscript/scriptingexample/GlobalRegistry.java Zobrazit soubor

@@ -0,0 +1,96 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.scriptingexample;
7
+
8
+import java.util.ArrayList;
9
+import java.util.HashMap;
10
+import java.util.List;
11
+import java.util.Map;
12
+import org.openzen.zenscript.codemodel.FunctionHeader;
13
+import org.openzen.zenscript.codemodel.FunctionParameter;
14
+import org.openzen.zenscript.codemodel.Modifiers;
15
+import org.openzen.zenscript.codemodel.definition.ClassDefinition;
16
+import org.openzen.zenscript.codemodel.definition.ExpansionDefinition;
17
+import org.openzen.zenscript.codemodel.definition.ZSPackage;
18
+import org.openzen.zenscript.codemodel.expression.GetStaticFieldExpression;
19
+import org.openzen.zenscript.codemodel.partial.IPartialExpression;
20
+import org.openzen.zenscript.codemodel.partial.PartialMemberGroupExpression;
21
+import org.openzen.zenscript.codemodel.type.BasicTypeID;
22
+import org.openzen.zenscript.codemodel.type.DefinitionTypeID;
23
+import org.openzen.zenscript.codemodel.type.FunctionTypeID;
24
+import org.openzen.zenscript.codemodel.type.GlobalTypeRegistry;
25
+import org.openzen.zenscript.codemodel.type.ITypeID;
26
+import org.openzen.zenscript.linker.symbol.ISymbol;
27
+import org.openzen.zenscript.shared.CodePosition;
28
+
29
+/**
30
+ *
31
+ * @author Hoofdgebruiker
32
+ */
33
+public class GlobalRegistry {
34
+	
35
+	
36
+	public ZSPackage collectPackages() {
37
+		ZSPackage rootPackage = new ZSPackage();
38
+		
39
+		// register packages here
40
+		
41
+		{
42
+			// eg. package my.package with a class MyClass with a single native method test() returning a string
43
+			// the visitors can then during compilation check if a method is an instance of NativeMethodMember and treat it accordingly
44
+			ClassDefinition myClassDefinition = new ClassDefinition("MyClass", Modifiers.MODIFIER_PUBLIC, null);
45
+			myClassDefinition.addMember(new NativeMethodMember(Modifiers.MODIFIER_PUBLIC, "test", new FunctionHeader(BasicTypeID.STRING), "Lmy/test/MyClass;", "()Ljava/lang/String;"));
46
+
47
+			ZSPackage packageMyPackage = rootPackage.getOrCreatePackage("my").getOrCreatePackage("package");
48
+			packageMyPackage.register(myClassDefinition);
49
+		}
50
+		
51
+		return rootPackage;
52
+	}
53
+	
54
+	public List<ExpansionDefinition> collectExpansions() {
55
+		List<ExpansionDefinition> expansions = new ArrayList<>();
56
+		
57
+		return expansions;
58
+	}
59
+	
60
+	public Map<String, ISymbol> collectGlobals() {
61
+		Map<String, ISymbol> globals = new HashMap<>();
62
+		
63
+		// for example, let's add a println global so we can call println("Hello world!") from anywhere
64
+		globals.put("println", new PrintlnSymbol());
65
+		
66
+		return globals;
67
+	}
68
+	
69
+	private static final ClassDefinition printStream = new ClassDefinition("PrintStream", Modifiers.MODIFIER_EXPORT, null);
70
+	private static final NativeMethodMember printStreamPrintln = new NativeMethodMember(
71
+			Modifiers.MODIFIER_EXPORT,
72
+			"println",
73
+			new FunctionHeader(BasicTypeID.VOID, new FunctionParameter(BasicTypeID.STRING)),
74
+			"Ljava/io/PrintStream;",
75
+			"(Ljava/lang/String;)V");
76
+	
77
+	private static final NativeFieldMember systemOut = new NativeFieldMember(Modifiers.MODIFIER_EXPORT, "out", DefinitionTypeID.forType(printStream), true, "java/lang/System");
78
+	
79
+	private class PrintlnSymbol implements ISymbol {
80
+
81
+		@Override
82
+		public IPartialExpression getExpression(CodePosition position, GlobalTypeRegistry types, List<ITypeID> typeArguments) {
83
+			return new PartialMemberGroupExpression(
84
+					position,
85
+					new GetStaticFieldExpression(position, systemOut),
86
+					printStreamPrintln,
87
+					false);
88
+		}
89
+
90
+		@Override
91
+		public ITypeID getType(CodePosition position, GlobalTypeRegistry types, List<ITypeID> typeArguments) {
92
+			// don't be fooled! this symbol is the System.out.println bound method and thus its type is a function
93
+			return new FunctionTypeID(printStreamPrintln.header);
94
+		}
95
+	}
96
+}

+ 52
- 0
ScriptingExample/src/main/java/org/openzen/zenscript/scriptingexample/JavaModule.java Zobrazit soubor

@@ -0,0 +1,52 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.scriptingexample;
7
+
8
+import java.lang.reflect.InvocationTargetException;
9
+import java.util.HashMap;
10
+import java.util.Map;
11
+import java.util.logging.Level;
12
+import java.util.logging.Logger;
13
+
14
+/**
15
+ *
16
+ * @author Hoofdgebruiker
17
+ */
18
+public class JavaModule {
19
+	private Map<String, byte[]> classes = new HashMap<>();
20
+	
21
+	public JavaModule() {
22
+		
23
+	}
24
+	
25
+	public void register(String classname, byte[] bytecode) {
26
+		classes.put(classname, bytecode);
27
+	}
28
+	
29
+	public void execute() {
30
+		ScriptClassLoader classLoader = new ScriptClassLoader();
31
+		
32
+		try {
33
+			classLoader.loadClass("Scripts").getMethod("run").invoke(null);
34
+		} catch (ClassNotFoundException ex) {
35
+			Logger.getLogger(JavaModule.class.getName()).log(Level.SEVERE, null, ex);
36
+		} catch (NoSuchMethodException ex) {
37
+			Logger.getLogger(JavaModule.class.getName()).log(Level.SEVERE, null, ex);
38
+		} catch (SecurityException ex) {
39
+			Logger.getLogger(JavaModule.class.getName()).log(Level.SEVERE, null, ex);
40
+		} catch (IllegalAccessException ex) {
41
+			Logger.getLogger(JavaModule.class.getName()).log(Level.SEVERE, null, ex);
42
+		} catch (IllegalArgumentException ex) {
43
+			Logger.getLogger(JavaModule.class.getName()).log(Level.SEVERE, null, ex);
44
+		} catch (InvocationTargetException ex) {
45
+			Logger.getLogger(JavaModule.class.getName()).log(Level.SEVERE, null, ex);
46
+		}
47
+	}
48
+	
49
+	private class ScriptClassLoader extends ClassLoader {
50
+		
51
+	}
52
+}

+ 95
- 0
ScriptingExample/src/main/java/org/openzen/zenscript/scriptingexample/Main.java Zobrazit soubor

@@ -0,0 +1,95 @@
1
+package org.openzen.zenscript.scriptingexample;
2
+
3
+import java.io.File;
4
+import java.io.IOException;
5
+import java.util.ArrayList;
6
+import java.util.List;
7
+import java.util.Map;
8
+import org.openzen.zenscript.codemodel.HighLevelDefinition;
9
+import org.openzen.zenscript.codemodel.PackageDefinitions;
10
+import org.openzen.zenscript.codemodel.ScriptBlock;
11
+import org.openzen.zenscript.codemodel.definition.ExpansionDefinition;
12
+import org.openzen.zenscript.codemodel.definition.ZSPackage;
13
+import org.openzen.zenscript.codemodel.type.GlobalTypeRegistry;
14
+import org.openzen.zenscript.linker.symbol.ISymbol;
15
+import org.openzen.zenscript.parser.ParsedFile;
16
+
17
+public class Main {
18
+    /**
19
+     * @param args the command line arguments
20
+     */
21
+    public static void main(String[] args) throws IOException {
22
+		File inputDirectory = new File("scripts");
23
+		File[] inputFiles = inputDirectory.listFiles((dir, name) -> name.endsWith(".zs"));
24
+		
25
+		ParsedFile[] parsedFiles = parse(inputFiles);
26
+		
27
+		GlobalRegistry registry = new GlobalRegistry();
28
+		SemanticModule module = compileSyntaxToSemantic(parsedFiles, registry);
29
+		
30
+		JavaModule javaModule = compileSemanticToJava(module);
31
+		javaModule.execute();
32
+    }
33
+	
34
+	private static ParsedFile[] parse(File[] files) throws IOException {
35
+		ParsedFile[] parsedFiles = new ParsedFile[files.length];
36
+		for (int i = 0; i < files.length; i++) {
37
+			parsedFiles[i] = ParsedFile.parse(files[i]);
38
+		}
39
+		return parsedFiles;
40
+	}
41
+	
42
+	private static SemanticModule compileSyntaxToSemantic(ParsedFile[] files, GlobalRegistry registry) {
43
+		// We are considering all these files to be in the same package, so make
44
+		// a single PackageDefinition instance. If these files were in multiple
45
+		// packages, we'd need an instance for every package.
46
+		PackageDefinitions definitions = new PackageDefinitions();
47
+		for (ParsedFile file : files) {
48
+			// listDefinitions will merely register all definitions (classes,
49
+			// interfaces, functions ...) so they can later be available to
50
+			// the other files as well. It doesn't yet compile anything.
51
+			file.listDefinitions(definitions);
52
+		}
53
+		
54
+		ZSPackage rootPackage = registry.collectPackages();
55
+		List<ExpansionDefinition> expansions = registry.collectExpansions();
56
+		Map<String, ISymbol> globals = registry.collectGlobals();
57
+		
58
+		GlobalTypeRegistry globalRegistry = new GlobalTypeRegistry();
59
+		for (ParsedFile file : files) {
60
+			// compileMembers will register all definition members to their
61
+			// respective definitions, such as fields, constructors, methods...
62
+			// It doesn't yet compile the method contents.
63
+			file.compileMembers(rootPackage, definitions, globalRegistry, expansions, globals);
64
+		}
65
+		
66
+		// scripts will store all the script blocks encountered in the files
67
+		List<ScriptBlock> scripts = new ArrayList<>();
68
+		for (ParsedFile file : files) {
69
+			// compileCode will convert the parsed statements and expressions
70
+			// into semantic code. This semantic code can then be compiled
71
+			// to various targets.
72
+			file.compileCode(rootPackage, definitions, globalRegistry, expansions, scripts, globals);
73
+		}
74
+		
75
+		return new SemanticModule(definitions, scripts);
76
+	}
77
+	
78
+	private static JavaModule compileSemanticToJava(SemanticModule module) {
79
+		JavaModule result = new JavaModule();
80
+		
81
+		// TODO: java bytecode compilation
82
+		for (HighLevelDefinition definition : module.definitions.getAll()) {
83
+			// convert definitions into java classes
84
+		}
85
+		
86
+		for (ScriptBlock script : module.scripts) {
87
+			// convert scripts into methods (add them to a Scripts class?)
88
+			// (TODO: can we break very long scripts into smaller methods? for the extreme scripts)
89
+		}
90
+		
91
+		// create a Scripts.run() method to run all scripts compiled above
92
+		
93
+		return result;
94
+	}
95
+}

+ 24
- 0
ScriptingExample/src/main/java/org/openzen/zenscript/scriptingexample/NativeFieldMember.java Zobrazit soubor

@@ -0,0 +1,24 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.scriptingexample;
7
+
8
+import org.openzen.zenscript.codemodel.member.FieldMember;
9
+import org.openzen.zenscript.codemodel.type.ITypeID;
10
+import org.openzen.zenscript.shared.CodePosition;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public class NativeFieldMember extends FieldMember {
17
+	public final String className;
18
+	
19
+	public NativeFieldMember(int modifiers, String name, ITypeID type, boolean isFinal, String className) {
20
+		super(CodePosition.NATIVE, modifiers, name, type, isFinal);
21
+		
22
+		this.className = className;
23
+	}
24
+}

+ 26
- 0
ScriptingExample/src/main/java/org/openzen/zenscript/scriptingexample/NativeMethodMember.java Zobrazit soubor

@@ -0,0 +1,26 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.scriptingexample;
7
+
8
+import org.openzen.zenscript.codemodel.FunctionHeader;
9
+import org.openzen.zenscript.codemodel.member.MethodMember;
10
+import org.openzen.zenscript.shared.CodePosition;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public class NativeMethodMember extends MethodMember {
17
+	public final String className;
18
+	public final String signature;
19
+
20
+	public NativeMethodMember(int modifiers, String name, FunctionHeader header, String className, String signature) {
21
+		super(CodePosition.NATIVE, modifiers, name, header);
22
+
23
+		this.className = className;
24
+		this.signature = signature;
25
+	}
26
+}

+ 24
- 0
ScriptingExample/src/main/java/org/openzen/zenscript/scriptingexample/SemanticModule.java Zobrazit soubor

@@ -0,0 +1,24 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.scriptingexample;
7
+
8
+import java.util.List;
9
+import org.openzen.zenscript.codemodel.PackageDefinitions;
10
+import org.openzen.zenscript.codemodel.ScriptBlock;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public class SemanticModule {
17
+	public final PackageDefinitions definitions;
18
+	public final List<ScriptBlock> scripts;
19
+
20
+	public SemanticModule(PackageDefinitions definitions, List<ScriptBlock> scripts) {
21
+		this.definitions = definitions;
22
+		this.scripts = scripts;
23
+	}
24
+}

Loading…
Zrušit
Uložit