Última actividad 2 days ago

capitalex's Avatar capitalex revisó este gist 2 days ago. Ir a la revisión

2 files changed, 119 insertions

compiler_wip.gd(archivo creado)

@@ -0,0 +1,92 @@
1 + extends RefCounted
2 + class_name NovaCompiler
3 + # NOTE: Godot's docs for array states that `.resize` + direct assignment is faster
4 + # than repeatedly calling `append` and `push_back`.
5 + static var prelude = """
6 + extends RefCounted
7 +
8 + var state = %s
9 +
10 + func push(stack_symbol, symbol) -> void:
11 + state[stack_symbol].push_back(symbol)
12 +
13 + func peek(stack_symbol, depth : int, symbol) -> bool:
14 + var stack = state[stack_symbol]
15 + if not stack: return false
16 + return stack[stack.size() - depth] == symbol
17 +
18 + func pop(stack_symbol) -> void:
19 + state[stack_symbol].pop_back()
20 + """
21 +
22 + static func compile(json_string: String) -> GDScript:
23 + var json = JSON.new()
24 + var error = json.parse(json_string)
25 + if error != OK:
26 + print("JSON Parse Error: ", json.get_error_message(), " in ", json_string, " at line ", json.get_error_line())
27 + return GDScript.new()
28 +
29 + var rules = json.data.rules
30 + var state = json.data.state
31 +
32 + var compiled_rules := PackedStringArray([prelude % state])
33 + var i := 0
34 +
35 + for rule in rules:
36 + var conditions = rule.conditions
37 + var results = rule.results
38 + compiled_rules.push_back("func _rule_%d() -> bool:" % i)
39 + var depths : Dictionary[String, int] = {}
40 + for condition in conditions:
41 + for action in condition.pattern:
42 + match action.type:
43 + "variable":
44 + # TODO: name mangle this
45 + compiled_rules.push_back("\tvar %s" % action.symbol)
46 + for condition in conditions:
47 + var stack : String = condition.stack.c_escape()
48 + for action in condition.pattern:
49 + var depth = depths.get_or_add(stack, 0)
50 + depths[stack] = depth + 1
51 + match action.type:
52 + "literal":
53 + compiled_rules.push_back("\tif not peek(\"%s\", %d, \"%s\"): return false" % [
54 + stack,
55 + depth,
56 + action.symbol.c_escape()
57 + ])
58 + "variable":
59 + compiled_rules.push_back("\tif %s == null and peek(\"%s\", %d, \"%s\"): return false" % [
60 + action.symbol.c_escape(),
61 + stack,
62 + depth,
63 + action.symbol.c_escape()
64 + ])
65 + compiled_rules.push_back("\t%s = peek(\"%s\", %d, \"%s\")" % [
66 + action.symbol.c_escape(),
67 + stack,
68 + depth,
69 + action.symbol.c_escape()
70 + ])
71 + for condition in conditions:
72 + var stack : String = condition.stack.c_escape()
73 + for __ in range(condition.pattern.size()):
74 + compiled_rules.push_back("\tpop(\"%s\")" % stack)
75 + for result in results:
76 + var stack : String = result.stack
77 + for action in result.pattern:
78 + match action.type:
79 + "literal":
80 + compiled_rules.push_back("\tpush(\"%s\", \"%s\")" % [
81 + stack, action.symbol.c_escape()
82 + ])
83 + "variable":
84 + compiled_rules.push_back("\tpush(\"%s\", %s if %s else \"%s\")" % [
85 + stack, action.symbol, action.symbol, action.symbol.c_escape()
86 + ])
87 + pass
88 + print(conditions)
89 + print(results)
90 + print("\n".join(compiled_rules))
91 +
92 + return GDScript.new()

progress.gd(archivo creado)

@@ -0,0 +1,27 @@
1 + extends RefCounted
2 +
3 + var state = { "foo": ["foo", "bar", "baz", "quux"], "bar": ["quux", "baz", "bar", "foo"] }
4 +
5 + func push(stack_symbol, symbol) -> void:
6 + state[stack_symbol].push_back(symbol)
7 +
8 + func peek(stack_symbol, depth : int, symbol) -> bool:
9 + var stack = state[stack_symbol]
10 + if not stack: return false
11 + return stack[stack.size() - depth] == symbol
12 +
13 + func pop(stack_symbol) -> void:
14 + state[stack_symbol].pop_back()
15 +
16 + func _rule_0() -> bool:
17 + var baz
18 + if not peek("foo", 0, "bar"): return false
19 + if baz == null and peek("foo", 1, "baz"): return false
20 + baz = peek("foo", 1, "baz")
21 + if not peek("foo", 2, "bin"): return false
22 + pop("foo")
23 + pop("foo")
24 + pop("foo")
25 + push("bar", "quux")
26 + push("bar", baz if baz else "baz")
27 + push("bar", "quin")
Siguiente Anterior