This commit is contained in:
@@ -1,15 +1,6 @@
|
||||
class_name Alt
|
||||
|
||||
static var behaviorMap: haxe_ds_StringMap = haxe_ds_StringMap.new().__set(">", AltBehavior.AltBehavior.Sequence)
|
||||
haxe_ds_StringMap.new().__set("!", AltBehavior.AltBehavior.OnceOnly)
|
||||
haxe_ds_StringMap.new().__set("&", AltBehavior.AltBehavior.Cycle)
|
||||
haxe_ds_StringMap.new().__set("%", AltBehavior.AltBehavior.Shuffle)
|
||||
haxe_ds_StringMap.new().__set("sequence:", AltBehavior.AltBehavior.Sequence)
|
||||
haxe_ds_StringMap.new().__set("once:", AltBehavior.AltBehavior.OnceOnly)
|
||||
haxe_ds_StringMap.new().__set("cycle:", AltBehavior.AltBehavior.Cycle)
|
||||
haxe_ds_StringMap.new().__set("shuffle:", AltBehavior.AltBehavior.Shuffle)
|
||||
|
||||
haxe_ds_StringMap.new()
|
||||
static var behaviorMap: Array[Variant] = []
|
||||
|
||||
var behavior: AltBehavior.AltBehavior
|
||||
var outputs: Array[Output]
|
||||
@@ -34,23 +25,53 @@ static func parse(buffer: HankBuffer) -> Variant:
|
||||
tempString = s
|
||||
|
||||
var expr: String = tempString
|
||||
|
||||
if (behaviorMap.size() == 0):
|
||||
behaviorMap.push_back({
|
||||
"key": ">",
|
||||
"value": AltBehavior.AltBehavior.Sequence
|
||||
})
|
||||
behaviorMap.push_back({
|
||||
"key": "!",
|
||||
"value": AltBehavior.AltBehavior.OnceOnly
|
||||
})
|
||||
behaviorMap.push_back({
|
||||
"key": "&",
|
||||
"value": AltBehavior.AltBehavior.Cycle
|
||||
})
|
||||
behaviorMap.push_back({
|
||||
"key": "%",
|
||||
"value": AltBehavior.AltBehavior.Shuffle
|
||||
})
|
||||
behaviorMap.push_back({
|
||||
"key": "sequence:",
|
||||
"value": AltBehavior.AltBehavior.Sequence
|
||||
})
|
||||
behaviorMap.push_back({
|
||||
"key": "once:",
|
||||
"value": AltBehavior.AltBehavior.OnceOnly
|
||||
})
|
||||
behaviorMap.push_back({
|
||||
"key": "cycle:",
|
||||
"value": AltBehavior.AltBehavior.Cycle
|
||||
})
|
||||
behaviorMap.push_back({
|
||||
"key": "shuffle:",
|
||||
"value": AltBehavior.AltBehavior.Shuffle
|
||||
})
|
||||
|
||||
var behavior2: AltBehavior.AltBehavior = AltBehavior.AltBehavior.Sequence
|
||||
var tempIterator
|
||||
|
||||
if true:
|
||||
var this1: Variant = behaviorMap
|
||||
tempIterator = this1.keys()
|
||||
|
||||
while (tempIterator.get("hasNext").call()):
|
||||
var prefix2: String = tempIterator.get("next").call()
|
||||
if (StringTools.startsWith(expr, prefix2)):
|
||||
expr = StringTools.trim(expr.substr(prefix2.length()))
|
||||
var tempRight
|
||||
if true:
|
||||
var this1: Variant = behaviorMap
|
||||
tempRight = this1.__get(prefix2)
|
||||
behavior2 = tempRight
|
||||
break
|
||||
var _g: int = 0
|
||||
var _g1: Array[Variant] = behaviorMap
|
||||
while (_g < _g1.size()):
|
||||
var prefix: Variant = _g1[_g]
|
||||
_g += 1
|
||||
if (StringTools.startsWith(expr, prefix.get("key"))):
|
||||
expr = StringTools.trim(expr.substr(prefix.get("key").length()))
|
||||
behavior2 = prefix.get("value")
|
||||
break
|
||||
|
||||
var outputsBuffer: HankBuffer = HankBuffer.Dummy(expr)
|
||||
var eachOutputExpr: Array[String] = outputsBuffer.rootSplit("|")
|
||||
@@ -58,25 +79,28 @@ static func parse(buffer: HankBuffer) -> Variant:
|
||||
if (eachOutputExpr.size() == 1):
|
||||
return { "_index": 1 }
|
||||
|
||||
var _g: Array[Output] = ([] as Array[Output])
|
||||
var _g1: int = 0
|
||||
var tempArray
|
||||
|
||||
while (_g1 < eachOutputExpr.size()):
|
||||
var outputExpr: String = eachOutputExpr[_g1]
|
||||
_g1 += 1
|
||||
var tempString1
|
||||
if true:
|
||||
var _g: Array[Output] = ([] as Array[Output])
|
||||
if true:
|
||||
var l: int = outputExpr.length()
|
||||
var r: int = 0
|
||||
while (r < l && StringTools.isSpace(outputExpr, r)):
|
||||
r += 1
|
||||
if (r > 0):
|
||||
tempString1 = outputExpr.substr(r, l - r)
|
||||
else:
|
||||
tempString1 = outputExpr
|
||||
_g.push_back(Output.parse(HankBuffer.Dummy(tempString1), true))
|
||||
var _g1: int = 0
|
||||
while (_g1 < eachOutputExpr.size()):
|
||||
var outputExpr: String = eachOutputExpr[_g1]
|
||||
_g1 += 1
|
||||
var tempString1
|
||||
if true:
|
||||
var l: int = outputExpr.length()
|
||||
var r: int = 0
|
||||
while (r < l && StringTools.isSpace(outputExpr, r)):
|
||||
r += 1
|
||||
if (r > 0):
|
||||
tempString1 = outputExpr.substr(r, l - r)
|
||||
else:
|
||||
tempString1 = outputExpr
|
||||
_g.push_back(Output.parse(HankBuffer.Dummy(tempString1), true))
|
||||
tempArray = _g
|
||||
|
||||
buffer.take(rawExpr.length())
|
||||
|
||||
return { "_index": 0, "v": Alt.new(behavior2, _g) }
|
||||
|
||||
return { "_index": 0, "v": Alt.new(behavior2, tempArray) }
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
class_name haxe__CallStack_CallStack_Impl_
|
||||
|
||||
func _init() -> void:
|
||||
pass
|
||||
|
||||
static func callStack() -> Array[Variant]:
|
||||
return haxe_NativeStackTrace.toHaxe(haxe_NativeStackTrace.callStack())
|
||||
|
||||
static func exceptionStack(fullStack: bool = false) -> Array[Variant]:
|
||||
var eStack: Array[Variant] = haxe_NativeStackTrace.toHaxe(haxe_NativeStackTrace.exceptionStack())
|
||||
var tempCallStack
|
||||
|
||||
if (fullStack):
|
||||
tempCallStack = eStack
|
||||
else:
|
||||
tempCallStack = haxe__CallStack_CallStack_Impl_.subtract(eStack, haxe__CallStack_CallStack_Impl_.callStack())
|
||||
|
||||
var this1: Array[Variant] = tempCallStack
|
||||
|
||||
return this1
|
||||
|
||||
static func subtract(this1: Array[Variant], stack: Array[Variant]) -> Array[Variant]:
|
||||
var startIndex: int = -1
|
||||
var i: int = -1
|
||||
|
||||
while true:
|
||||
var tempLeft
|
||||
i += 1
|
||||
tempLeft = i
|
||||
if !(tempLeft < this1.size()):
|
||||
break
|
||||
var _g: int = 0
|
||||
var _g1: int = stack.size()
|
||||
while (_g < _g1):
|
||||
var tempNumber
|
||||
_g += 1
|
||||
tempNumber = _g - 1
|
||||
var j: int = tempNumber
|
||||
if (haxe__CallStack_CallStack_Impl_.equalItems(this1[i], stack[j])):
|
||||
if (startIndex < 0):
|
||||
startIndex = i
|
||||
i += 1
|
||||
if (i >= this1.size()):
|
||||
break
|
||||
else:
|
||||
startIndex = -1
|
||||
if (startIndex >= 0):
|
||||
break
|
||||
|
||||
var tempResult
|
||||
|
||||
if (startIndex >= 0):
|
||||
tempResult = this1.slice(0, startIndex)
|
||||
else:
|
||||
tempResult = this1
|
||||
|
||||
return tempResult
|
||||
|
||||
static func equalItems(item1, item2) -> bool:
|
||||
var tempResult
|
||||
|
||||
if (item1 == null):
|
||||
if (item2 == null):
|
||||
tempResult = true
|
||||
else:
|
||||
tempResult = false
|
||||
else:
|
||||
match (item1._index):
|
||||
0:
|
||||
if (item2 == null):
|
||||
tempResult = false
|
||||
else:
|
||||
if (item2._index == 0):
|
||||
tempResult = true
|
||||
else:
|
||||
tempResult = false
|
||||
1:
|
||||
var _g: String = item1.m
|
||||
if (item2 == null):
|
||||
tempResult = false
|
||||
else:
|
||||
if (item2._index == 1):
|
||||
var _g1: String = item2.m
|
||||
var m2: String = _g1
|
||||
var m1: String = _g
|
||||
tempResult = m1 == m2
|
||||
else:
|
||||
tempResult = false
|
||||
2:
|
||||
var _g = item1.s
|
||||
var _g1: String = item1.file
|
||||
var _g2: int = item1.line
|
||||
var _g3 = item1.column
|
||||
if (item2 == null):
|
||||
tempResult = false
|
||||
else:
|
||||
if (item2._index == 2):
|
||||
var _g4 = item2.s
|
||||
var _g5: String = item2.file
|
||||
var _g6: int = item2.line
|
||||
var _g7 = item2.column
|
||||
var item3 = _g4
|
||||
var file2: String = _g5
|
||||
var line2: int = _g6
|
||||
var col2 = _g7
|
||||
var col1 = _g3
|
||||
var line1: int = _g2
|
||||
var file1: String = _g1
|
||||
var item4 = _g
|
||||
tempResult = file1 == file2 && line1 == line2 && col1 == col2 && haxe__CallStack_CallStack_Impl_.equalItems(item4, item3)
|
||||
else:
|
||||
tempResult = false
|
||||
3:
|
||||
var _g = item1.classname
|
||||
var _g1: String = item1.method
|
||||
if (item2 == null):
|
||||
tempResult = false
|
||||
else:
|
||||
if (item2._index == 3):
|
||||
var _g2 = item2.classname
|
||||
var _g3: String = item2.method
|
||||
var class2 = _g2
|
||||
var method2: String = _g3
|
||||
var method1: String = _g1
|
||||
var class1 = _g
|
||||
tempResult = class1 == class2 && method1 == method2
|
||||
else:
|
||||
tempResult = false
|
||||
4:
|
||||
var _g = item1.v
|
||||
if (item2 == null):
|
||||
tempResult = false
|
||||
else:
|
||||
if (item2._index == 4):
|
||||
var _g1 = item2.v
|
||||
var v2 = _g1
|
||||
var v1 = _g
|
||||
tempResult = v1 == v2
|
||||
else:
|
||||
tempResult = false
|
||||
|
||||
return tempResult
|
||||
|
||||
@@ -485,4 +485,3 @@ static func viewCountOf(viewCounts2: Variant, val) -> Variant:
|
||||
tempResult = { "_index": 1 }
|
||||
|
||||
return tempResult
|
||||
|
||||
|
||||
@@ -8,54 +8,6 @@ var ast: Array[Variant] = []
|
||||
|
||||
func _init() -> void:
|
||||
choices = 0
|
||||
symbols.push_back({
|
||||
"key": "INCLUDE ",
|
||||
"value": HParser.include
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "<-",
|
||||
"value": HParser.thread
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "->",
|
||||
"value": HParser.divert
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "===",
|
||||
"value": HParser.knot
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "==",
|
||||
"value": HParser.knot
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "=",
|
||||
"value": HParser.stitch
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "~",
|
||||
"value": HParser.haxeLine
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "```",
|
||||
"value": HParser.haxeBlock
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "-",
|
||||
"value": HParser.gather
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "*",
|
||||
"value": HParser.choice
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "+",
|
||||
"value": HParser.choice
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "#",
|
||||
"value": HParser.tag
|
||||
})
|
||||
|
||||
func parseString(h: String) -> Array[Variant]:
|
||||
var stringBuffer: HankBuffer = HankBuffer.Dummy(h)
|
||||
@@ -148,6 +100,56 @@ func parseFile(f: String, files = null, includedFile: bool = false) -> Array[Var
|
||||
return parsedAST
|
||||
|
||||
static func parseExpr(buffer: HankBuffer, position: Position) -> Variant:
|
||||
if (symbols.size() == 0):
|
||||
symbols.push_back({
|
||||
"key": "INCLUDE ",
|
||||
"value": HParser.include
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "<-",
|
||||
"value": HParser.thread
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "->",
|
||||
"value": HParser.divert
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "===",
|
||||
"value": HParser.knot
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "==",
|
||||
"value": HParser.knot
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "=",
|
||||
"value": HParser.stitch
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "~",
|
||||
"value": HParser.haxeLine
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "```",
|
||||
"value": HParser.haxeBlock
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "-",
|
||||
"value": HParser.gather
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "*",
|
||||
"value": HParser.choice
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "+",
|
||||
"value": HParser.choice
|
||||
})
|
||||
symbols.push_back({
|
||||
"key": "#",
|
||||
"value": HParser.tag
|
||||
})
|
||||
|
||||
var line: Variant = buffer.peekLine("")
|
||||
|
||||
match (line._index):
|
||||
@@ -311,7 +313,7 @@ static func tag(buffer: HankBuffer, position: Position) -> Variant:
|
||||
else:
|
||||
haxe_Log.trace.call("Warning! Can't apply tags to " + str(expr), {
|
||||
"fileName": "../hank/HParser.hx",
|
||||
"lineNumber": 234,
|
||||
"lineNumber": 236,
|
||||
"className": "hank.HParser",
|
||||
"methodName": "tag"
|
||||
})
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
class_name HankAssert
|
||||
|
||||
func _init() -> void:
|
||||
pass
|
||||
|
||||
static func _assert(condition: bool, message: String) -> void:
|
||||
if (condition):
|
||||
HankAssert._pass(message)
|
||||
else:
|
||||
HankAssert.fail(message)
|
||||
|
||||
static func _pass(message: String) -> void:
|
||||
message = " ✓" + message
|
||||
LogUtil.cleanTrace(message)
|
||||
|
||||
static func fail(message: String) -> void:
|
||||
message = " ✗" + message
|
||||
LogUtil.cleanTrace(message)
|
||||
|
||||
static func equals(expected, actual, pos = null) -> void:
|
||||
var verboseMessage: String = " Asserting that " + str(actual) + " is expected value " + str(expected)
|
||||
|
||||
HankAssert._assert(str(expected) == str(actual), verboseMessage)
|
||||
|
||||
static func contains(expected: String, actual: String) -> void:
|
||||
var verboseMessage: String = " Asserting that \"" + actual + "\" contains \"" + expected + "\""
|
||||
|
||||
HankAssert._assert(actual.find(expected) != -1, verboseMessage)
|
||||
|
||||
static func notContains(unexpected: String, actual: String) -> void:
|
||||
var verboseMessage: String = " Asserting that \"" + actual + "\" does not contain \"" + unexpected + "\""
|
||||
|
||||
HankAssert._assert(actual.find(unexpected) == -1, verboseMessage)
|
||||
|
||||
static func isSome(option: Variant) -> void:
|
||||
var verboseMessage: String = " Asserting that " + str(option) + " is Some(_)"
|
||||
|
||||
match (option._index):
|
||||
0:
|
||||
var _g = option.v
|
||||
HankAssert._pass(verboseMessage)
|
||||
1:
|
||||
HankAssert.fail(verboseMessage)
|
||||
|
||||
static func isNone(option: Variant) -> void:
|
||||
var verboseMessage: String = " Asserting that " + str(option) + " is None"
|
||||
|
||||
match (option._index):
|
||||
0:
|
||||
var _g = option.v
|
||||
HankAssert.fail(verboseMessage)
|
||||
1:
|
||||
HankAssert._pass(verboseMessage)
|
||||
|
||||
static func throws(f, message = null) -> void:
|
||||
if true:
|
||||
f.call()
|
||||
HankAssert.fail("Expected an exception to be thrown")
|
||||
|
||||
@@ -113,6 +113,8 @@ func rootIndexOf(s: String) -> int:
|
||||
return start
|
||||
start += 1
|
||||
|
||||
return -1
|
||||
|
||||
func rootSplit(delimiter: String) -> Array[String]:
|
||||
var rootIndices: Array[int] = self.everyRootIndexOf(delimiter)
|
||||
|
||||
@@ -444,7 +446,8 @@ static func Dummy(text: String) -> HankBuffer:
|
||||
return HankBuffer.new("_", text, 1, 1)
|
||||
|
||||
static func FromFile(path2: String, files = null) -> HankBuffer:
|
||||
var rawBuffer2: String = File.getContent(path2)
|
||||
var rawBuffer2: String = ""
|
||||
|
||||
rawBuffer2 = FileAccess.open(path2, FileAccess.READ).get_as_text()
|
||||
|
||||
return HankBuffer.new(path2, rawBuffer2)
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ func initOps() -> void:
|
||||
return v1 * v2)
|
||||
self.assignOp("/=", func(v1: float, v2: float) -> float:
|
||||
return v1 / v2)
|
||||
self.assignOp("%=", func(v1: float, v2: float) -> float:
|
||||
self.assignOp("%=", func(v1: int, v2: int) -> int:
|
||||
return v1 % v2)
|
||||
self.assignOp("&=", func(v1: int, v2: int) -> int:
|
||||
return v1 & v2)
|
||||
@@ -838,13 +838,10 @@ func expr(e: Variant):
|
||||
if (isAllString):
|
||||
tempVar1 = haxe_ds_StringMap.new()
|
||||
else:
|
||||
if (isAllEnum):
|
||||
tempVar1 = haxe_ds_EnumValueMap.new()
|
||||
if (isAllObject):
|
||||
tempVar1 = haxe_ds_ObjectMap.new()
|
||||
else:
|
||||
if (isAllObject):
|
||||
tempVar1 = haxe_ds_ObjectMap.new()
|
||||
else:
|
||||
assert(false, str("Inconsistent key types"))
|
||||
assert(false, str("Inconsistent key types"))
|
||||
var map = tempVar1
|
||||
if true:
|
||||
var _g2: int = 0
|
||||
@@ -1091,10 +1088,4 @@ func _call(o, f, args: Array[Variant]):
|
||||
return f.callv(args)
|
||||
|
||||
func cnew(cl: String, args: Array[Variant]):
|
||||
var c: Class = Type.resolveClass(cl)
|
||||
|
||||
if (c == null):
|
||||
c = self.resolve(cl)
|
||||
|
||||
return Type.createInstance(c, args)
|
||||
|
||||
return null
|
||||
|
||||
@@ -266,6 +266,8 @@ static func parseBraceExpression(buffer: HankBuffer) -> Variant:
|
||||
else:
|
||||
return Output.parseHaxeExpression(buffer)
|
||||
|
||||
return null
|
||||
|
||||
static func parseHaxeExpression(buffer: HankBuffer) -> Variant:
|
||||
var rawExpression: String = Extensions.unwrap(buffer.findNestedExpression("{", "}", 0, true)).checkValue()
|
||||
var hExpression: String = rawExpression.substr(1, rawExpression.length() - 2)
|
||||
@@ -285,4 +287,3 @@ static func appendNextText(story: Story, fullOutput: String, throwOnFail: String
|
||||
assert(false, str(throwOnFail))
|
||||
|
||||
return fullOutput
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ func _init() -> void:
|
||||
self.opChars = "+*/-=!><&|^%~"
|
||||
self.identChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"
|
||||
|
||||
var priorities: Array[Array[String]] = ([(["%"] as Array[String]), (["*", "/"] as Array[String]), (["+", "-"] as Array[String]), (["<<", ">>", ">>>"] as Array[String]), (["|", "&", "^"] as Array[String]), (["==", "!=", ">", "<", ">=", "<="] as Array[String]), (["..."] as Array[String]), (["&&"] as Array[String]), (["||"] as Array[String]), (["=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "|=", "&=", "^=", "=>"] as Array[String]), (["->"] as Array[String])] as Array[Array[String]])
|
||||
var priorities: Array[Variant] = ([(["%"] as Array[Variant]), (["*", "/"] as Array[Variant]), (["+", "-"] as Array[Variant]), (["<<", ">>", ">>>"] as Array[Variant]), (["|", "&", "^"] as Array[Variant]), (["==", "!=", ">", "<", ">=", "<="] as Array[Variant]), (["..."] as Array[Variant]), (["&&"] as Array[Variant]), (["||"] as Array[Variant]), (["=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "|=", "&=", "^=", "=>"] as Array[Variant]), (["->"] as Array[Variant])] as Array[Variant])
|
||||
|
||||
self.opPriority = haxe_ds_StringMap.new()
|
||||
self.opRightAssoc = haxe_ds_StringMap.new()
|
||||
@@ -37,10 +37,10 @@ func _init() -> void:
|
||||
_g += 1
|
||||
tempNumber = _g - 1
|
||||
var i: int = tempNumber
|
||||
var p: Array[Variant] = (priorities[i] as Array[Variant])
|
||||
var _g2: int = 0
|
||||
var _g3: Array[String] = priorities[i]
|
||||
while (_g2 < _g3.size()):
|
||||
var x: String = _g3[_g2]
|
||||
while (_g2 < p.size()):
|
||||
var x = p[_g2]
|
||||
_g2 += 1
|
||||
self.opPriority.__set(x, i)
|
||||
if (i == 9):
|
||||
@@ -173,13 +173,13 @@ func ensure(tk) -> void:
|
||||
if (t != tk):
|
||||
self.unexpected(t)
|
||||
|
||||
func ensureToken(tk) -> void:
|
||||
func ensureToken(tk: Variant) -> void:
|
||||
var t = self.token()
|
||||
|
||||
if (!Type.enumEq(t, tk)):
|
||||
self.unexpected(t)
|
||||
|
||||
func maybe(tk) -> bool:
|
||||
func maybe(tk: Variant) -> bool:
|
||||
var t = self.token()
|
||||
|
||||
if (Type.enumEq(t, tk)):
|
||||
@@ -196,7 +196,7 @@ func getIdent() -> String:
|
||||
|
||||
if (tk == null):
|
||||
self.unexpected(tk)
|
||||
return null
|
||||
return ""
|
||||
else:
|
||||
if (tk._index == 2):
|
||||
var _g: String = tk.s
|
||||
@@ -204,7 +204,7 @@ func getIdent() -> String:
|
||||
return id
|
||||
else:
|
||||
self.unexpected(tk)
|
||||
return null
|
||||
return ""
|
||||
|
||||
func expr(e: Variant) -> Variant:
|
||||
return e
|
||||
@@ -475,7 +475,7 @@ func parseExpr():
|
||||
tk = self.token()
|
||||
if (tk == { "_index": 5 }):
|
||||
if true:
|
||||
var tk2 = { "_index": 3, "s": "->" }
|
||||
var tk2: Variant = { "_index": 3, "s": "->" }
|
||||
var t = self.token()
|
||||
if (!Type.enumEq(t, tk2)):
|
||||
self.unexpected(t)
|
||||
@@ -706,7 +706,7 @@ func parseLambda(args: Array[Variant], pmin) -> Variant:
|
||||
break
|
||||
|
||||
if true:
|
||||
var tk = { "_index": 3, "s": "->" }
|
||||
var tk: Variant = { "_index": 3, "s": "->" }
|
||||
var t = self.token()
|
||||
if (!Type.enumEq(t, tk)):
|
||||
self.unexpected(t)
|
||||
@@ -937,7 +937,7 @@ func parseStructure(id: String):
|
||||
self.unexpected(t)
|
||||
var vname: String = self.getIdent()
|
||||
if true:
|
||||
var tk = { "_index": 2, "s": "in" }
|
||||
var tk: Variant = { "_index": 2, "s": "in" }
|
||||
var t = self.token()
|
||||
if (!Type.enumEq(t, tk)):
|
||||
self.unexpected(t)
|
||||
@@ -1180,7 +1180,7 @@ func parseStructure(id: String):
|
||||
"try":
|
||||
var e = self.parseExpr()
|
||||
if true:
|
||||
var tk = { "_index": 2, "s": "catch" }
|
||||
var tk: Variant = { "_index": 2, "s": "catch" }
|
||||
var t = self.token()
|
||||
if (!Type.enumEq(t, tk)):
|
||||
self.unexpected(t)
|
||||
@@ -1197,7 +1197,7 @@ func parseStructure(id: String):
|
||||
if (self.allowTypes):
|
||||
t = self.parseType()
|
||||
else:
|
||||
var tk = { "_index": 2, "s": "Dynamic" }
|
||||
var tk: Variant = { "_index": 2, "s": "Dynamic" }
|
||||
var t2 = self.token()
|
||||
if (!Type.enumEq(t2, tk)):
|
||||
self.unexpected(t2)
|
||||
@@ -1756,6 +1756,8 @@ func parseType() -> Variant:
|
||||
_:
|
||||
return self.unexpected(t)
|
||||
|
||||
return null
|
||||
|
||||
func parseTypeNext(t: Variant) -> Variant:
|
||||
var tk = self.token()
|
||||
|
||||
@@ -1980,7 +1982,7 @@ func parseModuleDecl() -> Variant:
|
||||
var name: String = self.getIdent()
|
||||
var params: Variant = self.parseParams()
|
||||
if true:
|
||||
var tk = { "_index": 3, "s": "=" }
|
||||
var tk: Variant = { "_index": 3, "s": "=" }
|
||||
var t = self.token()
|
||||
if (!Type.enumEq(t, tk)):
|
||||
self.unexpected(t)
|
||||
@@ -2655,6 +2657,8 @@ func evalPreproCond(e: Variant) -> bool:
|
||||
assert(false, str(err))
|
||||
return false
|
||||
|
||||
return false
|
||||
|
||||
func preprocess(id: String) -> Variant:
|
||||
match (id):
|
||||
"else", "elseif":
|
||||
@@ -2846,4 +2850,3 @@ func tokenString(t: Variant) -> String:
|
||||
tempResult = "#" + id
|
||||
|
||||
return tempResult
|
||||
|
||||
|
||||
@@ -405,4 +405,3 @@ static func bound(Value: float, Min = null, Max = null) -> float:
|
||||
tempResult = lowerBound
|
||||
|
||||
return tempResult
|
||||
|
||||
|
||||
@@ -776,4 +776,3 @@ static func FromFile(script: String, files = null, randomSeed = null) -> Story:
|
||||
var ast2: Array[Variant] = parser2.parseFile(script, files, false)
|
||||
|
||||
return Story.FromAST(script, ast2, randomSeed)
|
||||
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
class_name StoryTestCase
|
||||
|
||||
var testsDirectory: String
|
||||
var files: Variant = haxe_ds_StringMap.new()
|
||||
var lastTranscriptLine: int = 0
|
||||
|
||||
func _init(testsDirectory2: String, preloadedFiles = null) -> void:
|
||||
self.testsDirectory = testsDirectory2
|
||||
|
||||
if (preloadedFiles != null):
|
||||
self.files = preloadedFiles
|
||||
|
||||
func testAllExamples() -> void:
|
||||
var exampleTranscripts: Variant = haxe_ds_StringMap.new()
|
||||
var exampleFolders: Array[String] = FileSystem.readDirectory(self.testsDirectory)
|
||||
|
||||
if true:
|
||||
var _g: int = 0
|
||||
while (_g < exampleFolders.size()):
|
||||
var folder: String = exampleFolders[_g]
|
||||
_g += 1
|
||||
var files2: Array[String] = FileSystem.readDirectory("" + self.testsDirectory + "/" + folder)
|
||||
if true:
|
||||
var tempArray
|
||||
if true:
|
||||
var _g2: Array[String] = ([] as Array[String])
|
||||
if true:
|
||||
var _g1: int = 0
|
||||
while (_g1 < files2.size()):
|
||||
var file: String = files2[_g1]
|
||||
_g1 += 1
|
||||
if (StringTools.endsWith(file, ".hlog")):
|
||||
_g2.push_back(file)
|
||||
tempArray = _g2
|
||||
var value: Array[String] = tempArray
|
||||
exampleTranscripts.__set(folder, value)
|
||||
if true:
|
||||
var folder: Variant = exampleTranscripts.keys()
|
||||
while (folder.get("hasNext").call()):
|
||||
var folder2: String = folder.get("next").call()
|
||||
if (StringTools.startsWith(folder2, "_")):
|
||||
LogUtil.cleanTrace(" Skipping tests for example \"" + folder2 + "\"")
|
||||
continue
|
||||
LogUtil.cleanTrace(" Running tests for example \"" + folder2 + "\"")
|
||||
if true:
|
||||
var _g: int = 0
|
||||
var _g1 = exampleTranscripts.__get(folder2)
|
||||
while (_g < _g1.size()):
|
||||
var file: String = _g1[_g]
|
||||
_g += 1
|
||||
var disabled: bool = file.find("disabled") != -1
|
||||
var debug: bool = file.find("debug") != -1
|
||||
var partial: bool = file.find("partial") != -1
|
||||
if (!disabled):
|
||||
LogUtil.cleanTrace(" Running " + file)
|
||||
self.validateAgainstTranscript("" + self.testsDirectory + "/" + folder2 + "/main.hank", "" + self.testsDirectory + "/" + folder2 + "/" + file, !partial, debug)
|
||||
|
||||
func validateAgainstTranscript(storyFile: String, transcriptFile: String, fullTranscript: bool = true, debug: bool = false) -> void:
|
||||
var buffer: HankBuffer = HankBuffer.FromFile(transcriptFile, self.files)
|
||||
var transcriptLines: Array[String] = buffer.lines()
|
||||
var randomSeed = null
|
||||
|
||||
if (StringTools.startsWith(transcriptLines[0], "@")):
|
||||
randomSeed = transcriptLines[0].substr(1).to_int()
|
||||
if true:
|
||||
var index: int = transcriptLines.find(transcriptLines[0])
|
||||
if (index >= 0):
|
||||
transcriptLines.remove_at(index)
|
||||
true
|
||||
else:
|
||||
false
|
||||
|
||||
var story: Story = null
|
||||
|
||||
story = Story.FromFile(storyFile, self.files, randomSeed)
|
||||
|
||||
story.hInterface.addVariable("DEBUG", debug)
|
||||
|
||||
var i: int = 0
|
||||
|
||||
while (i < transcriptLines.size()):
|
||||
var line: String = transcriptLines[i]
|
||||
self.lastTranscriptLine = i
|
||||
if (StringTools.startsWith(line, "#")):
|
||||
var tempArray
|
||||
var _this: String = StringTools.trim(line.substr(1))
|
||||
tempArray = Array(Array(_this.split(":")), Variant.Type.TYPE_STRING, "", null)
|
||||
var parts: Array[String] = tempArray
|
||||
HankAssert.equals(StringTools.trim(parts[1]), story.hInterface.evaluateExpr(parts[0], story.nodeScopes), null)
|
||||
i += 1
|
||||
continue
|
||||
var frame: Variant = story.nextFrame()
|
||||
if (StringTools.startsWith(line, "*")):
|
||||
var choices: Array[String] = []
|
||||
while true:
|
||||
choices.push_back(line.substr(2))
|
||||
var tempIndex
|
||||
i += 1
|
||||
tempIndex = i
|
||||
line = transcriptLines[tempIndex]
|
||||
if !(line != null && StringTools.startsWith(line, "*")):
|
||||
break
|
||||
var tempArray1
|
||||
var _g: Array[Variant] = ([] as Array[Variant])
|
||||
var _g1: int = 0
|
||||
while (_g1 < choices.size()):
|
||||
var choice: String = choices[_g1]
|
||||
_g1 += 1
|
||||
_g.push_back(([] as Array[Variant]))
|
||||
tempArray1 = _g
|
||||
HankAssert.equals({ "_index": 1, "choices": choices, "tags": tempArray1 }, frame, null)
|
||||
continue
|
||||
else:
|
||||
if (StringTools.startsWith(line, ">")):
|
||||
var tempRight
|
||||
var s: String = line.substr(1)
|
||||
var l: int = s.length()
|
||||
var r: int = 0
|
||||
while (r < l && StringTools.isSpace(s, r)):
|
||||
r += 1
|
||||
if (r > 0):
|
||||
tempRight = s.substr(r, l - r)
|
||||
else:
|
||||
tempRight = s
|
||||
line = tempRight
|
||||
var firstColonIdx: int = line.find(":")
|
||||
if (firstColonIdx == -1):
|
||||
assert(false, str("Choice line in transcript does not specify expected output: > " + line))
|
||||
var index: int = line.substr(0, firstColonIdx).to_int() - 1
|
||||
var expectedOutput: String = StringTools.trim(line.substr(firstColonIdx + 1))
|
||||
var output: String = story.choose(index)
|
||||
HankAssert.equals(expectedOutput, output, null)
|
||||
else:
|
||||
if (line.length() > 0):
|
||||
HankAssert.equals({ "_index": 0, "text": line }, frame, null)
|
||||
if (frame == { "_index": 2 }):
|
||||
break
|
||||
i += 1
|
||||
|
||||
if (fullTranscript):
|
||||
HankAssert.equals({ "_index": 2 }, story.nextFrame(), null)
|
||||
|
||||
10
hank-godot/scripts/Type.gd
Normal file
10
hank-godot/scripts/Type.gd
Normal file
@@ -0,0 +1,10 @@
|
||||
class_name Type
|
||||
|
||||
func _init() -> void:
|
||||
pass
|
||||
|
||||
static func enumEq(a, b) -> bool:
|
||||
return false
|
||||
|
||||
static func enumConstructor(e) -> String:
|
||||
return ""
|
||||
@@ -1,13 +1,9 @@
|
||||
{
|
||||
"filesGenerated": [
|
||||
"tests_Examples.gd",
|
||||
"sys_FileSeek.gd",
|
||||
"plugin.gd",
|
||||
"plugin.cfg",
|
||||
"hscript_Interp_Stop.gd",
|
||||
"hscript_Expr_FieldAccess.gd",
|
||||
"haxe_ds_GenericStack_GenericCell.gd",
|
||||
"haxe_ds_BalancedTree_TreeNode.gd",
|
||||
"haxe_StringMap.gd",
|
||||
"haxe_StringKeyValueIterator.gd",
|
||||
"haxe_StringIterator.gd",
|
||||
@@ -17,12 +13,12 @@
|
||||
"haxe_MapKeyValueIterator.gd",
|
||||
"haxe_IntMap.gd",
|
||||
"haxe_GenericStack.gd",
|
||||
"haxe_EnumValueMap.gd",
|
||||
"haxe_Encoding.gd",
|
||||
"haxe_BalancedTree.gd",
|
||||
"haxe_ArrayIterator.gd",
|
||||
"hank_Story_EmbedMode.gd",
|
||||
"hank_StoryTree_StoryNode.gd",
|
||||
"hank_Parser_Type.gd",
|
||||
"hank_Interp_Stop.gd",
|
||||
"hank_HankBuffer_Position.gd",
|
||||
"hank_HankBuffer_BufferSlice.gd",
|
||||
"hank_HankAST_ASTExtension.gd",
|
||||
@@ -34,7 +30,6 @@
|
||||
"SysTools.gd",
|
||||
"StringTools.gd",
|
||||
"StringBuf.gd",
|
||||
"StoryTestCase.gd",
|
||||
"Story.gd",
|
||||
"Reflect.gd",
|
||||
"Random.gd",
|
||||
@@ -45,16 +40,14 @@
|
||||
"Interp.gd",
|
||||
"IntIterator.gd",
|
||||
"HankBuffer.gd",
|
||||
"HankAssert.gd",
|
||||
"HParser.gd",
|
||||
"HInterface.gd",
|
||||
"Extensions.gd",
|
||||
"Exception.gd",
|
||||
"EReg.gd",
|
||||
"CallStack.gd",
|
||||
"Alt.gd"
|
||||
],
|
||||
"id": 33,
|
||||
"id": 62,
|
||||
"wasCached": false,
|
||||
"version": 1
|
||||
}
|
||||
@@ -7,6 +7,7 @@ var story: Story
|
||||
func _init(hInterface2: HInterface) -> void:
|
||||
self.hInterface = hInterface2
|
||||
|
||||
super()
|
||||
|
||||
func setStory(story2: Story) -> void:
|
||||
self.story = story2
|
||||
@@ -115,4 +116,3 @@ func assign(e1: Variant, e2: Variant):
|
||||
return super.assign(e1, e2)
|
||||
else:
|
||||
return super.assign(e1, e2)
|
||||
|
||||
|
||||
11
hank-godot/scripts/hank_Parser_Type.gd
Normal file
11
hank-godot/scripts/hank_Parser_Type.gd
Normal file
@@ -0,0 +1,11 @@
|
||||
class_name Type
|
||||
|
||||
func _init() -> void:
|
||||
pass
|
||||
|
||||
static func enumEq(a, b) -> bool:
|
||||
return false
|
||||
|
||||
static func enumConstructor(e) -> String:
|
||||
return ""
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
class_name haxe_ds_BalancedTree
|
||||
|
||||
var root: haxe_ds_TreeNode
|
||||
|
||||
func _init() -> void:
|
||||
pass
|
||||
|
||||
func __set(key, value) -> void:
|
||||
self.root = self.setLoop(key, value, self.root)
|
||||
|
||||
func __get(key):
|
||||
var node: haxe_ds_TreeNode = self.root
|
||||
|
||||
while (node != null):
|
||||
var c: int = self.compare(key, node.key)
|
||||
if (c == 0):
|
||||
return node.value
|
||||
if (c < 0):
|
||||
node = node.left
|
||||
else:
|
||||
node = node.right
|
||||
|
||||
return null
|
||||
|
||||
func keys() -> Variant:
|
||||
var ret: Array[Variant] = ([] as Array[Variant])
|
||||
|
||||
self.keysLoop(self.root, ret)
|
||||
|
||||
return haxe_iterators_ArrayIterator.new(ret)
|
||||
|
||||
func setLoop(k, v, node: haxe_ds_TreeNode) -> haxe_ds_TreeNode:
|
||||
if (node == null):
|
||||
return haxe_ds_TreeNode.new(null, k, v, null)
|
||||
|
||||
var c: int = self.compare(k, node.key)
|
||||
var tempResult
|
||||
|
||||
if (c == 0):
|
||||
var tempNumber
|
||||
if (node == null):
|
||||
tempNumber = 0
|
||||
else:
|
||||
tempNumber = node._height
|
||||
tempResult = haxe_ds_TreeNode.new(node.left, k, v, node.right, tempNumber)
|
||||
else:
|
||||
if (c < 0):
|
||||
var nl: haxe_ds_TreeNode = self.setLoop(k, v, node.left)
|
||||
tempResult = self.balance(nl, node.key, node.value, node.right)
|
||||
else:
|
||||
var nr: haxe_ds_TreeNode = self.setLoop(k, v, node.right)
|
||||
tempResult = self.balance(node.left, node.key, node.value, nr)
|
||||
|
||||
return tempResult
|
||||
|
||||
func keysLoop(node: haxe_ds_TreeNode, acc: Array[Variant]) -> void:
|
||||
if (node != null):
|
||||
self.keysLoop(node.left, acc)
|
||||
acc.push_back(node.key)
|
||||
self.keysLoop(node.right, acc)
|
||||
|
||||
func balance(l: haxe_ds_TreeNode, k, v, r: haxe_ds_TreeNode) -> haxe_ds_TreeNode:
|
||||
var tempNumber
|
||||
|
||||
if (l == null):
|
||||
tempNumber = 0
|
||||
else:
|
||||
tempNumber = l._height
|
||||
|
||||
var hl: int = tempNumber
|
||||
var tempNumber1
|
||||
|
||||
if (r == null):
|
||||
tempNumber1 = 0
|
||||
else:
|
||||
tempNumber1 = r._height
|
||||
|
||||
var hr: int = tempNumber1
|
||||
var tempResult
|
||||
|
||||
if (hl > hr + 2):
|
||||
var tempLeft
|
||||
if true:
|
||||
var _this: haxe_ds_TreeNode = l.left
|
||||
if (_this == null):
|
||||
tempLeft = 0
|
||||
else:
|
||||
tempLeft = _this._height
|
||||
var tempRight
|
||||
if true:
|
||||
var _this: haxe_ds_TreeNode = l.right
|
||||
if (_this == null):
|
||||
tempRight = 0
|
||||
else:
|
||||
tempRight = _this._height
|
||||
if (tempLeft >= tempRight):
|
||||
tempResult = haxe_ds_TreeNode.new(l.left, l.key, l.value, haxe_ds_TreeNode.new(l.right, k, v, r))
|
||||
else:
|
||||
tempResult = haxe_ds_TreeNode.new(haxe_ds_TreeNode.new(l.left, l.key, l.value, l.right.left), l.right.key, l.right.value, haxe_ds_TreeNode.new(l.right.right, k, v, r))
|
||||
else:
|
||||
if (hr > hl + 2):
|
||||
var tempLeft1
|
||||
if true:
|
||||
var _this: haxe_ds_TreeNode = r.right
|
||||
if (_this == null):
|
||||
tempLeft1 = 0
|
||||
else:
|
||||
tempLeft1 = _this._height
|
||||
var tempRight1
|
||||
if true:
|
||||
var _this: haxe_ds_TreeNode = r.left
|
||||
if (_this == null):
|
||||
tempRight1 = 0
|
||||
else:
|
||||
tempRight1 = _this._height
|
||||
if (tempLeft1 > tempRight1):
|
||||
tempResult = haxe_ds_TreeNode.new(haxe_ds_TreeNode.new(l, k, v, r.left), r.key, r.value, r.right)
|
||||
else:
|
||||
tempResult = haxe_ds_TreeNode.new(haxe_ds_TreeNode.new(l, k, v, r.left.left), r.left.key, r.left.value, haxe_ds_TreeNode.new(r.left.right, r.key, r.value, r.right))
|
||||
else:
|
||||
var tempNumber2
|
||||
if (hl > hr):
|
||||
tempNumber2 = hl
|
||||
else:
|
||||
tempNumber2 = hr
|
||||
tempResult = haxe_ds_TreeNode.new(l, k, v, r, (tempNumber2) + 1)
|
||||
|
||||
return tempResult
|
||||
|
||||
func compare(k1, k2) -> int:
|
||||
return Reflect.compare(k1, k2)
|
||||
|
||||
@@ -50,4 +50,3 @@ func compareArg(v1, v2) -> int:
|
||||
tempResult = Reflect.compare(v1, v2)
|
||||
|
||||
return tempResult
|
||||
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
class_name haxe_ds_TreeNode
|
||||
|
||||
var left: haxe_ds_TreeNode
|
||||
var right: haxe_ds_TreeNode
|
||||
var key
|
||||
var value
|
||||
var _height: int
|
||||
|
||||
func _init(l: haxe_ds_TreeNode, k, v, r: haxe_ds_TreeNode, h: int = -1) -> void:
|
||||
self.left = l
|
||||
self.key = k
|
||||
self.value = v
|
||||
self.right = r
|
||||
|
||||
if (h == -1):
|
||||
var tempNumber
|
||||
var tempLeft
|
||||
if true:
|
||||
var _this: haxe_ds_TreeNode = self.left
|
||||
if (_this == null):
|
||||
tempLeft = 0
|
||||
else:
|
||||
tempLeft = _this._height
|
||||
var tempRight
|
||||
if true:
|
||||
var _this: haxe_ds_TreeNode = self.right
|
||||
if (_this == null):
|
||||
tempRight = 0
|
||||
else:
|
||||
tempRight = _this._height
|
||||
if (tempLeft > tempRight):
|
||||
var _this: haxe_ds_TreeNode = self.left
|
||||
if (_this == null):
|
||||
tempNumber = 0
|
||||
else:
|
||||
tempNumber = _this._height
|
||||
else:
|
||||
var _this: haxe_ds_TreeNode = self.right
|
||||
if (_this == null):
|
||||
tempNumber = 0
|
||||
else:
|
||||
tempNumber = _this._height
|
||||
self._height = (tempNumber) + 1
|
||||
else:
|
||||
self._height = h
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
class_name FileSeek extends Object
|
||||
|
||||
enum FileSeek {
|
||||
SeekBegin,
|
||||
SeekCur,
|
||||
SeekEnd,
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
class_name Examples
|
||||
|
||||
static var files: Variant = haxe_ds_StringMap.new()
|
||||
static var fileBuffer = func(path: String) -> HankBuffer:
|
||||
return HankBuffer.new(path, files.__get(path))
|
||||
|
||||
func _init() -> void:
|
||||
pass
|
||||
|
||||
static func main() -> void:
|
||||
haxe_Log.trace.call("Testing examples for target " + LogUtil.currentTarget(), {
|
||||
"fileName": "../tests/main/Examples.hx",
|
||||
"lineNumber": 8,
|
||||
"className": "tests.main.Examples",
|
||||
"methodName": "main"
|
||||
})
|
||||
StoryTestCase.new("examples").testAllExamples()
|
||||
|
||||
30
hank/Alt.hx
30
hank/Alt.hx
@@ -19,16 +19,7 @@ class Alt {
|
||||
var behavior:AltBehavior;
|
||||
var outputs:Array<Output>;
|
||||
|
||||
static var behaviorMap = [
|
||||
'>' => Sequence,
|
||||
'!' => OnceOnly,
|
||||
'&' => Cycle,
|
||||
'%' => Shuffle,
|
||||
'sequence:' => Sequence,
|
||||
'once:' => OnceOnly,
|
||||
'cycle:' => Cycle,
|
||||
'shuffle:' => Shuffle
|
||||
];
|
||||
static var behaviorMap:Array<{key:String, value:AltBehavior}> = [];
|
||||
|
||||
public function new(behavior:AltBehavior, outputs:Array<Output>) {
|
||||
this.behavior = behavior;
|
||||
@@ -41,12 +32,23 @@ class Alt {
|
||||
var expr = rawExpr.substr(1, rawExpr.length - 2).ltrim();
|
||||
// trace (expr);
|
||||
|
||||
if(behaviorMap.length == 0) {
|
||||
behaviorMap.push({key: '>', value: Sequence});
|
||||
behaviorMap.push({key: '!', value: OnceOnly});
|
||||
behaviorMap.push({key: '&', value: Cycle});
|
||||
behaviorMap.push({key: '%', value: Shuffle});
|
||||
behaviorMap.push({key: 'sequence:', value: Sequence});
|
||||
behaviorMap.push({key: 'once:', value: OnceOnly});
|
||||
behaviorMap.push({key: 'cycle:', value: Cycle});
|
||||
behaviorMap.push({key: 'shuffle:', value: Shuffle});
|
||||
}
|
||||
|
||||
// Sequences are the default behavior
|
||||
var behavior = Sequence;
|
||||
for (prefix in behaviorMap.keys()) {
|
||||
if (expr.startsWith(prefix)) {
|
||||
expr = expr.substr(prefix.length).trim();
|
||||
behavior = behaviorMap[prefix];
|
||||
for (prefix in behaviorMap) {
|
||||
if (expr.startsWith(prefix.key)) {
|
||||
expr = expr.substr(prefix.key.length).trim();
|
||||
behavior = prefix.value;
|
||||
break; // <-- Finally figured that one out.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ using Reflect;
|
||||
using Type;
|
||||
|
||||
import haxe.ds.Option;
|
||||
import hscript.Parser;
|
||||
import hscript.Interp;
|
||||
import hank.Parser;
|
||||
import hank.Interp;
|
||||
import hscript.Expr;
|
||||
|
||||
using hank.Extensions;
|
||||
@@ -24,6 +24,9 @@ class HankInterp extends Interp {
|
||||
public function new(hInterface:HInterface) {
|
||||
this.hInterface = hInterface;
|
||||
super();
|
||||
#if gdscript
|
||||
untyped __gdscript__("super()");
|
||||
#end
|
||||
}
|
||||
|
||||
public override function expr(e:Expr):Dynamic {
|
||||
|
||||
@@ -20,18 +20,6 @@ class HParser {
|
||||
|
||||
public function new() {
|
||||
choices = 0;
|
||||
symbols.push({key: 'INCLUDE ', value: include});
|
||||
symbols.push({key: '<-', value: thread});
|
||||
symbols.push({key: '->', value: divert});
|
||||
symbols.push({key: '===', value: knot});
|
||||
symbols.push({key: '==', value: knot});
|
||||
symbols.push({key: '=', value: stitch});
|
||||
symbols.push({key: '~', value: haxeLine});
|
||||
symbols.push({key: '```', value: haxeBlock});
|
||||
symbols.push({key: '-', value: gather});
|
||||
symbols.push({key: '*', value: choice});
|
||||
symbols.push({key: '+', value: choice});
|
||||
symbols.push({key: '#', value: tag});
|
||||
}
|
||||
|
||||
public function parseString(h:String):HankAST {
|
||||
@@ -102,6 +90,20 @@ class HParser {
|
||||
}
|
||||
|
||||
static function parseExpr(buffer:HankBuffer, position:HankBuffer.Position):ExprType {
|
||||
if (symbols.length == 0) {
|
||||
symbols.push({key: 'INCLUDE ', value: include});
|
||||
symbols.push({key: '<-', value: thread});
|
||||
symbols.push({key: '->', value: divert});
|
||||
symbols.push({key: '===', value: knot});
|
||||
symbols.push({key: '==', value: knot});
|
||||
symbols.push({key: '=', value: stitch});
|
||||
symbols.push({key: '~', value: haxeLine});
|
||||
symbols.push({key: '```', value: haxeBlock});
|
||||
symbols.push({key: '-', value: gather});
|
||||
symbols.push({key: '*', value: choice});
|
||||
symbols.push({key: '+', value: choice});
|
||||
symbols.push({key: '#', value: tag});
|
||||
};
|
||||
var line = buffer.peekLine();
|
||||
switch (line) {
|
||||
case None:
|
||||
|
||||
@@ -88,15 +88,18 @@ class HankBuffer {
|
||||
|
||||
public static function FromFile(path:String, ?files:PreloadedFiles) {
|
||||
// Keep a raw buffer of the file for tracking accurate file positions
|
||||
#if (sys || hxnodejs)
|
||||
var rawBuffer = sys.io.File.getContent(path);
|
||||
var rawBuffer:String = "";
|
||||
#if gdscript
|
||||
untyped __gdscript__('{0} = FileAccess.open({1}, FileAccess.READ).get_as_text()', rawBuffer, path);
|
||||
#elseif (sys || hxnodejs)
|
||||
rawBuffer = sys.io.File.getContent(path);
|
||||
#else
|
||||
if (files == null) {
|
||||
throw 'Tried to open file $path on a non-sys platform without passing in preloaded files';
|
||||
} else if (!files.exists(path)) {
|
||||
throw 'Tried to open file $path that was not pre-loaded';
|
||||
}
|
||||
var rawBuffer = files[path];
|
||||
rawBuffer = files[path];
|
||||
#end
|
||||
return new HankBuffer(path, rawBuffer);
|
||||
}
|
||||
@@ -148,6 +151,7 @@ class HankBuffer {
|
||||
}
|
||||
start += 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function rootSplit(delimiter:String):Array<String> {
|
||||
|
||||
707
hank/Interp.hx
Normal file
707
hank/Interp.hx
Normal file
@@ -0,0 +1,707 @@
|
||||
/*
|
||||
* Copyright (C)2008-2017 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package hank;
|
||||
import haxe.PosInfos;
|
||||
import hscript.Expr;
|
||||
import haxe.Constraints.IMap;
|
||||
import hscript.Tools;
|
||||
|
||||
private enum Stop {
|
||||
SBreak;
|
||||
SContinue;
|
||||
SReturn;
|
||||
}
|
||||
|
||||
class Interp {
|
||||
|
||||
#if haxe3
|
||||
public var variables : Map<String,Dynamic>;
|
||||
var locals : Map<String,{ r : Dynamic }>;
|
||||
var binops : Map<String, Expr -> Expr -> Dynamic >;
|
||||
#else
|
||||
public var variables : Hash<Dynamic>;
|
||||
var locals : Hash<{ r : Dynamic }>;
|
||||
var binops : Hash< Expr -> Expr -> Dynamic >;
|
||||
#end
|
||||
|
||||
var depth : Int;
|
||||
var inTry : Bool;
|
||||
var declared : Array<{ n : String, old : { r : Dynamic } }>;
|
||||
var returnValue : Dynamic;
|
||||
|
||||
#if hscriptPos
|
||||
var curExpr : Expr;
|
||||
#end
|
||||
|
||||
public function new() {
|
||||
#if haxe3
|
||||
locals = new Map();
|
||||
#else
|
||||
locals = new Hash();
|
||||
#end
|
||||
declared = new Array();
|
||||
resetVariables();
|
||||
initOps();
|
||||
}
|
||||
|
||||
private function resetVariables(){
|
||||
#if haxe3
|
||||
variables = new Map<String,Dynamic>();
|
||||
#else
|
||||
variables = new Hash();
|
||||
#end
|
||||
|
||||
variables.set("null",null);
|
||||
variables.set("true",true);
|
||||
variables.set("false",false);
|
||||
variables.set("trace", Reflect.makeVarArgs(function(el) {
|
||||
var inf = posInfos();
|
||||
var v = el.shift();
|
||||
if( el.length > 0 ) inf.customParams = el;
|
||||
haxe.Log.trace(Std.string(v), inf);
|
||||
}));
|
||||
}
|
||||
|
||||
public function posInfos(): PosInfos {
|
||||
#if hscriptPos
|
||||
if (curExpr != null)
|
||||
return cast { fileName : curExpr.origin, lineNumber : curExpr.line };
|
||||
#end
|
||||
return cast { fileName : "hscript", lineNumber : 0 };
|
||||
}
|
||||
|
||||
function initOps() {
|
||||
var me = this;
|
||||
#if haxe3
|
||||
binops = new Map();
|
||||
#else
|
||||
binops = new Hash();
|
||||
#end
|
||||
binops.set("+",function(e1,e2) return me.expr(e1) + me.expr(e2));
|
||||
binops.set("-",function(e1,e2) return me.expr(e1) - me.expr(e2));
|
||||
binops.set("*",function(e1,e2) return me.expr(e1) * me.expr(e2));
|
||||
binops.set("/",function(e1,e2) return me.expr(e1) / me.expr(e2));
|
||||
binops.set("%",function(e1,e2) return me.expr(e1) % me.expr(e2));
|
||||
binops.set("&",function(e1,e2) return me.expr(e1) & me.expr(e2));
|
||||
binops.set("|",function(e1,e2) return me.expr(e1) | me.expr(e2));
|
||||
binops.set("^",function(e1,e2) return me.expr(e1) ^ me.expr(e2));
|
||||
binops.set("<<",function(e1,e2) return me.expr(e1) << me.expr(e2));
|
||||
binops.set(">>",function(e1,e2) return me.expr(e1) >> me.expr(e2));
|
||||
binops.set(">>>",function(e1,e2) return me.expr(e1) >>> me.expr(e2));
|
||||
binops.set("==",function(e1,e2) return me.expr(e1) == me.expr(e2));
|
||||
binops.set("!=",function(e1,e2) return me.expr(e1) != me.expr(e2));
|
||||
binops.set(">=",function(e1,e2) return me.expr(e1) >= me.expr(e2));
|
||||
binops.set("<=",function(e1,e2) return me.expr(e1) <= me.expr(e2));
|
||||
binops.set(">",function(e1,e2) return me.expr(e1) > me.expr(e2));
|
||||
binops.set("<",function(e1,e2) return me.expr(e1) < me.expr(e2));
|
||||
binops.set("||",function(e1,e2) return me.expr(e1) == true || me.expr(e2) == true);
|
||||
binops.set("&&",function(e1,e2) return me.expr(e1) == true && me.expr(e2) == true);
|
||||
binops.set("=",assign);
|
||||
binops.set("...",function(e1,e2) return new #if (haxe_211 || haxe3) IntIterator #else IntIter #end(me.expr(e1),me.expr(e2)));
|
||||
assignOp("+=",function(v1:Dynamic,v2:Dynamic) return v1 + v2);
|
||||
assignOp("-=",function(v1:Float,v2:Float) return v1 - v2);
|
||||
assignOp("*=",function(v1:Float,v2:Float) return v1 * v2);
|
||||
assignOp("/=",function(v1:Float,v2:Float) return v1 / v2);
|
||||
assignOp("%=",function(v1:Int,v2:Int) return v1 % v2);
|
||||
assignOp("&=",function(v1,v2) return v1 & v2);
|
||||
assignOp("|=",function(v1,v2) return v1 | v2);
|
||||
assignOp("^=",function(v1,v2) return v1 ^ v2);
|
||||
assignOp("<<=",function(v1,v2) return v1 << v2);
|
||||
assignOp(">>=",function(v1,v2) return v1 >> v2);
|
||||
assignOp(">>>=",function(v1,v2) return v1 >>> v2);
|
||||
}
|
||||
|
||||
function setVar( name : String, v : Dynamic ) {
|
||||
variables.set(name, v);
|
||||
}
|
||||
|
||||
function assign( e1 : Expr, e2 : Expr ) : Dynamic {
|
||||
var v = expr(e2);
|
||||
switch( Tools.expr(e1) ) {
|
||||
case EIdent(id):
|
||||
var l = locals.get(id);
|
||||
if( l == null )
|
||||
setVar(id,v)
|
||||
else
|
||||
l.r = v;
|
||||
case EField(e,f):
|
||||
v = set(expr(e),f,v);
|
||||
case EArray(e, index):
|
||||
var arr:Dynamic = expr(e);
|
||||
var index:Dynamic = expr(index);
|
||||
if (isMap(arr)) {
|
||||
setMapValue(arr, index, v);
|
||||
}
|
||||
else {
|
||||
arr[index] = v;
|
||||
}
|
||||
|
||||
default:
|
||||
error(EInvalidOp("="));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
function assignOp( op, fop : Dynamic -> Dynamic -> Dynamic ) {
|
||||
var me = this;
|
||||
binops.set(op,function(e1,e2) return me.evalAssignOp(op,fop,e1,e2));
|
||||
}
|
||||
|
||||
function evalAssignOp(op,fop,e1,e2) : Dynamic {
|
||||
var v;
|
||||
switch( Tools.expr(e1) ) {
|
||||
case EIdent(id):
|
||||
var l = locals.get(id);
|
||||
v = fop(expr(e1),expr(e2));
|
||||
if( l == null )
|
||||
setVar(id,v)
|
||||
else
|
||||
l.r = v;
|
||||
case EField(e,f):
|
||||
var obj = expr(e);
|
||||
v = fop(get(obj,f),expr(e2));
|
||||
v = set(obj,f,v);
|
||||
case EArray(e, index):
|
||||
var arr:Dynamic = expr(e);
|
||||
var index:Dynamic = expr(index);
|
||||
if (isMap(arr)) {
|
||||
v = fop(getMapValue(arr, index), expr(e2));
|
||||
setMapValue(arr, index, v);
|
||||
}
|
||||
else {
|
||||
v = fop(arr[index],expr(e2));
|
||||
arr[index] = v;
|
||||
}
|
||||
default:
|
||||
return error(EInvalidOp(op));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
function increment( e : Expr, prefix : Bool, delta : Int ) : Dynamic {
|
||||
#if hscriptPos
|
||||
curExpr = e;
|
||||
var e = e.e;
|
||||
#end
|
||||
switch(e) {
|
||||
case EIdent(id):
|
||||
var l = locals.get(id);
|
||||
var v : Dynamic = (l == null) ? resolve(id) : l.r;
|
||||
if( prefix ) {
|
||||
v += delta;
|
||||
if( l == null ) setVar(id,v) else l.r = v;
|
||||
} else
|
||||
if( l == null ) setVar(id,v + delta) else l.r = v + delta;
|
||||
return v;
|
||||
case EField(e,f):
|
||||
var obj = expr(e);
|
||||
var v : Dynamic = get(obj,f);
|
||||
if( prefix ) {
|
||||
v += delta;
|
||||
set(obj,f,v);
|
||||
} else
|
||||
set(obj,f,v + delta);
|
||||
return v;
|
||||
case EArray(e, index):
|
||||
var arr:Dynamic = expr(e);
|
||||
var index:Dynamic = expr(index);
|
||||
if (isMap(arr)) {
|
||||
var v = getMapValue(arr, index);
|
||||
if (prefix) {
|
||||
v += delta;
|
||||
setMapValue(arr, index, v);
|
||||
}
|
||||
else {
|
||||
setMapValue(arr, index, v + delta);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
else {
|
||||
var v = arr[index];
|
||||
if( prefix ) {
|
||||
v += delta;
|
||||
arr[index] = v;
|
||||
} else
|
||||
arr[index] = v + delta;
|
||||
return v;
|
||||
}
|
||||
default:
|
||||
return error(EInvalidOp((delta > 0)?"++":"--"));
|
||||
}
|
||||
}
|
||||
|
||||
public function execute( expr : Expr ) : Dynamic {
|
||||
depth = 0;
|
||||
#if haxe3
|
||||
locals = new Map();
|
||||
#else
|
||||
locals = new Hash();
|
||||
#end
|
||||
declared = new Array();
|
||||
return exprReturn(expr);
|
||||
}
|
||||
|
||||
function exprReturn(e) : Dynamic {
|
||||
try {
|
||||
return expr(e);
|
||||
} catch( e : Stop ) {
|
||||
switch( e ) {
|
||||
case SBreak: throw "Invalid break";
|
||||
case SContinue: throw "Invalid continue";
|
||||
case SReturn:
|
||||
var v = returnValue;
|
||||
returnValue = null;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function duplicate<T>( h : #if haxe3 Map < String, T > #else Hash<T> #end ) {
|
||||
#if haxe3
|
||||
var h2 = new Map();
|
||||
#else
|
||||
var h2 = new Hash();
|
||||
#end
|
||||
for( k in h.keys() )
|
||||
h2.set(k,h.get(k));
|
||||
return h2;
|
||||
}
|
||||
|
||||
function restore( old : Int ) {
|
||||
while( declared.length > old ) {
|
||||
var d = declared.pop();
|
||||
locals.set(d.n,d.old);
|
||||
}
|
||||
}
|
||||
|
||||
inline function error(e : #if hscriptPos ErrorDef #else Error #end, rethrow=false ) : Dynamic {
|
||||
#if hscriptPos var e = new Error(e, curExpr.pmin, curExpr.pmax, curExpr.origin, curExpr.line); #end
|
||||
if( rethrow ) this.rethrow(e) else throw e;
|
||||
return null;
|
||||
}
|
||||
|
||||
inline function rethrow( e : Dynamic ) {
|
||||
#if hl
|
||||
hl.Api.rethrow(e);
|
||||
#else
|
||||
throw e;
|
||||
#end
|
||||
}
|
||||
|
||||
function resolve( id : String ) : Dynamic {
|
||||
var l = locals.get(id);
|
||||
if( l != null )
|
||||
return l.r;
|
||||
var v = variables.get(id);
|
||||
if( v == null && !variables.exists(id) )
|
||||
error(EUnknownVariable(id));
|
||||
return v;
|
||||
}
|
||||
|
||||
public function expr( e : Expr ) : Dynamic {
|
||||
#if hscriptPos
|
||||
curExpr = e;
|
||||
var e = e.e;
|
||||
#end
|
||||
switch( e ) {
|
||||
case EConst(c):
|
||||
switch( c ) {
|
||||
case CInt(v): return v;
|
||||
case CFloat(f): return f;
|
||||
case CString(s): return s;
|
||||
#if !haxe3
|
||||
case CInt32(v): return v;
|
||||
#end
|
||||
}
|
||||
case EIdent(id):
|
||||
return resolve(id);
|
||||
case EVar(n,_,e):
|
||||
declared.push({ n : n, old : locals.get(n) });
|
||||
locals.set(n,{ r : (e == null)?null:expr(e) });
|
||||
return null;
|
||||
case EParent(e):
|
||||
return expr(e);
|
||||
case EBlock(exprs):
|
||||
var old = declared.length;
|
||||
var v = null;
|
||||
for( e in exprs )
|
||||
v = expr(e);
|
||||
restore(old);
|
||||
return v;
|
||||
case EField(e,f):
|
||||
return get(expr(e),f);
|
||||
case EBinop(op,e1,e2):
|
||||
var fop = binops.get(op);
|
||||
if( fop == null ) error(EInvalidOp(op));
|
||||
return fop(e1,e2);
|
||||
case EUnop(op,prefix,e):
|
||||
switch(op) {
|
||||
case "!":
|
||||
return expr(e) != true;
|
||||
case "-":
|
||||
return -expr(e);
|
||||
case "++":
|
||||
return increment(e,prefix,1);
|
||||
case "--":
|
||||
return increment(e,prefix,-1);
|
||||
case "~":
|
||||
#if (neko && !haxe3)
|
||||
return haxe.Int32.complement(expr(e));
|
||||
#else
|
||||
return ~expr(e);
|
||||
#end
|
||||
default:
|
||||
error(EInvalidOp(op));
|
||||
}
|
||||
case ECall(e,params):
|
||||
var args = new Array();
|
||||
for( p in params )
|
||||
args.push(expr(p));
|
||||
|
||||
switch( Tools.expr(e) ) {
|
||||
case EField(e,f):
|
||||
var obj = expr(e);
|
||||
if( obj == null ) error(EInvalidAccess(f));
|
||||
return fcall(obj,f,args);
|
||||
default:
|
||||
return call(null,expr(e),args);
|
||||
}
|
||||
case EIf(econd,e1,e2):
|
||||
return if( expr(econd) == true ) expr(e1) else if( e2 == null ) null else expr(e2);
|
||||
case EWhile(econd,e):
|
||||
whileLoop(econd,e);
|
||||
return null;
|
||||
case EDoWhile(econd,e):
|
||||
doWhileLoop(econd,e);
|
||||
return null;
|
||||
case EFor(v,it,e):
|
||||
forLoop(v,it,e);
|
||||
return null;
|
||||
case EBreak:
|
||||
throw SBreak;
|
||||
case EContinue:
|
||||
throw SContinue;
|
||||
case EReturn(e):
|
||||
returnValue = e == null ? null : expr(e);
|
||||
throw SReturn;
|
||||
case EFunction(params,fexpr,name,_):
|
||||
var capturedLocals = duplicate(locals);
|
||||
var me = this;
|
||||
var hasOpt = false, minParams = 0;
|
||||
for( p in params )
|
||||
if( p.opt )
|
||||
hasOpt = true;
|
||||
else
|
||||
minParams++;
|
||||
var f = function(args:Array<Dynamic>) {
|
||||
if( ( (args == null) ? 0 : args.length ) != params.length ) {
|
||||
if( args.length < minParams ) {
|
||||
var str = "Invalid number of parameters. Got " + args.length + ", required " + minParams;
|
||||
if( name != null ) str += " for function '" + name+"'";
|
||||
error(ECustom(str));
|
||||
}
|
||||
// make sure mandatory args are forced
|
||||
var args2 = [];
|
||||
var extraParams = args.length - minParams;
|
||||
var pos = 0;
|
||||
for( p in params )
|
||||
if( p.opt ) {
|
||||
if( extraParams > 0 ) {
|
||||
args2.push(args[pos++]);
|
||||
extraParams--;
|
||||
} else
|
||||
args2.push(null);
|
||||
} else
|
||||
args2.push(args[pos++]);
|
||||
args = args2;
|
||||
}
|
||||
var old = me.locals, depth = me.depth;
|
||||
me.depth++;
|
||||
me.locals = me.duplicate(capturedLocals);
|
||||
for( i in 0...params.length )
|
||||
me.locals.set(params[i].name,{ r : args[i] });
|
||||
var r = null;
|
||||
var oldDecl = declared.length;
|
||||
if( inTry )
|
||||
try {
|
||||
r = me.exprReturn(fexpr);
|
||||
} catch( e : Dynamic ) {
|
||||
me.locals = old;
|
||||
me.depth = depth;
|
||||
#if neko
|
||||
neko.Lib.rethrow(e);
|
||||
#else
|
||||
throw e;
|
||||
#end
|
||||
}
|
||||
else
|
||||
r = me.exprReturn(fexpr);
|
||||
restore(oldDecl);
|
||||
me.locals = old;
|
||||
me.depth = depth;
|
||||
return r;
|
||||
};
|
||||
var f = Reflect.makeVarArgs(f);
|
||||
if( name != null ) {
|
||||
if( depth == 0 ) {
|
||||
// global function
|
||||
variables.set(name, f);
|
||||
} else {
|
||||
// function-in-function is a local function
|
||||
declared.push( { n : name, old : locals.get(name) } );
|
||||
var ref = { r : f };
|
||||
locals.set(name, ref);
|
||||
capturedLocals.set(name, ref); // allow self-recursion
|
||||
}
|
||||
}
|
||||
return f;
|
||||
case EArrayDecl(arr):
|
||||
if (arr.length > 0 && Tools.expr(arr[0]).match(EBinop("=>", _))) {
|
||||
var isAllString:Bool = true;
|
||||
var isAllInt:Bool = true;
|
||||
var isAllObject:Bool = true;
|
||||
var isAllEnum:Bool = true;
|
||||
var keys:Array<Dynamic> = [];
|
||||
var values:Array<Dynamic> = [];
|
||||
for (e in arr) {
|
||||
switch(Tools.expr(e)) {
|
||||
case EBinop("=>", eKey, eValue): {
|
||||
var key:Dynamic = expr(eKey);
|
||||
var value:Dynamic = expr(eValue);
|
||||
isAllString = isAllString && (key is String);
|
||||
isAllInt = isAllInt && (key is Int);
|
||||
isAllObject = isAllObject && Reflect.isObject(key);
|
||||
isAllEnum = isAllEnum && Reflect.isEnumValue(key);
|
||||
keys.push(key);
|
||||
values.push(value);
|
||||
}
|
||||
default: throw("=> expected");
|
||||
}
|
||||
}
|
||||
var map:Dynamic = {
|
||||
if (isAllInt) new haxe.ds.IntMap<Dynamic>();
|
||||
else if (isAllString) new haxe.ds.StringMap<Dynamic>();
|
||||
#if !gdscript
|
||||
else if (isAllEnum) new haxe.ds.EnumValueMap<Dynamic, Dynamic>();
|
||||
#end
|
||||
else if (isAllObject) new haxe.ds.ObjectMap<Dynamic, Dynamic>();
|
||||
else throw 'Inconsistent key types';
|
||||
}
|
||||
for (n in 0...keys.length) {
|
||||
setMapValue(map, keys[n], values[n]);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
else {
|
||||
var a = new Array();
|
||||
for ( e in arr ) {
|
||||
a.push(expr(e));
|
||||
}
|
||||
return a;
|
||||
}
|
||||
case EArray(e, index):
|
||||
var arr:Dynamic = expr(e);
|
||||
var index:Dynamic = expr(index);
|
||||
if (isMap(arr)) {
|
||||
return getMapValue(arr, index);
|
||||
}
|
||||
else {
|
||||
return arr[index];
|
||||
}
|
||||
case ENew(cl,params):
|
||||
var a = new Array();
|
||||
for( e in params )
|
||||
a.push(expr(e));
|
||||
return cnew(cl,a);
|
||||
case EThrow(e):
|
||||
throw expr(e);
|
||||
case ETry(e,n,_,ecatch):
|
||||
var old = declared.length;
|
||||
var oldTry = inTry;
|
||||
try {
|
||||
inTry = true;
|
||||
var v : Dynamic = expr(e);
|
||||
restore(old);
|
||||
inTry = oldTry;
|
||||
return v;
|
||||
} catch( err : Stop ) {
|
||||
inTry = oldTry;
|
||||
throw err;
|
||||
} catch( err : Dynamic ) {
|
||||
// restore vars
|
||||
restore(old);
|
||||
inTry = oldTry;
|
||||
// declare 'v'
|
||||
declared.push({ n : n, old : locals.get(n) });
|
||||
locals.set(n,{ r : err });
|
||||
var v : Dynamic = expr(ecatch);
|
||||
restore(old);
|
||||
return v;
|
||||
}
|
||||
case EObject(fl):
|
||||
var o = {};
|
||||
for( f in fl )
|
||||
set(o,f.name,expr(f.e));
|
||||
return o;
|
||||
case ETernary(econd,e1,e2):
|
||||
return if( expr(econd) == true ) expr(e1) else expr(e2);
|
||||
case ESwitch(e, cases, def):
|
||||
var val : Dynamic = expr(e);
|
||||
var match = false;
|
||||
for( c in cases ) {
|
||||
for( v in c.values )
|
||||
if( expr(v) == val ) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
if( match ) {
|
||||
val = expr(c.expr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !match )
|
||||
val = def == null ? null : expr(def);
|
||||
return val;
|
||||
case EMeta(_, _, e):
|
||||
return expr(e);
|
||||
case ECheckType(e,_):
|
||||
return expr(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function doWhileLoop(econd,e) {
|
||||
var old = declared.length;
|
||||
do {
|
||||
try {
|
||||
expr(e);
|
||||
} catch( err : Stop ) {
|
||||
switch(err) {
|
||||
case SContinue:
|
||||
case SBreak: break;
|
||||
case SReturn: throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
while( expr(econd) == true );
|
||||
restore(old);
|
||||
}
|
||||
|
||||
function whileLoop(econd,e) {
|
||||
var old = declared.length;
|
||||
while( expr(econd) == true ) {
|
||||
try {
|
||||
expr(e);
|
||||
} catch( err : Stop ) {
|
||||
switch(err) {
|
||||
case SContinue:
|
||||
case SBreak: break;
|
||||
case SReturn: throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
restore(old);
|
||||
}
|
||||
|
||||
function makeIterator( v : Dynamic ) : Iterator<Dynamic> {
|
||||
#if ((flash && !flash9) || (php && !php7 && haxe_ver < '4.0.0'))
|
||||
if ( v.iterator != null ) v = v.iterator();
|
||||
#else
|
||||
try v = v.iterator() catch( e : Dynamic ) {};
|
||||
#end
|
||||
if( v.hasNext == null || v.next == null ) error(EInvalidIterator(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
function forLoop(n,it,e) {
|
||||
var old = declared.length;
|
||||
declared.push({ n : n, old : locals.get(n) });
|
||||
var it = makeIterator(expr(it));
|
||||
while( it.hasNext() ) {
|
||||
locals.set(n,{ r : it.next() });
|
||||
try {
|
||||
expr(e);
|
||||
} catch( err : Stop ) {
|
||||
switch( err ) {
|
||||
case SContinue:
|
||||
case SBreak: break;
|
||||
case SReturn: throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
restore(old);
|
||||
}
|
||||
|
||||
inline function isMap(o:Dynamic):Bool {
|
||||
return (o is IMap);
|
||||
}
|
||||
|
||||
inline function getMapValue(map:Dynamic, key:Dynamic):Dynamic {
|
||||
return cast(map, haxe.Constraints.IMap<Dynamic, Dynamic>).get(key);
|
||||
}
|
||||
|
||||
inline function setMapValue(map:Dynamic, key:Dynamic, value:Dynamic):Void {
|
||||
cast(map, haxe.Constraints.IMap<Dynamic, Dynamic>).set(key, value);
|
||||
}
|
||||
|
||||
function get( o : Dynamic, f : String ) : Dynamic {
|
||||
if ( o == null ) error(EInvalidAccess(f));
|
||||
return {
|
||||
#if php
|
||||
// https://github.com/HaxeFoundation/haxe/issues/4915
|
||||
try {
|
||||
Reflect.getProperty(o, f);
|
||||
} catch (e:Dynamic) {
|
||||
Reflect.field(o, f);
|
||||
}
|
||||
#else
|
||||
Reflect.getProperty(o, f);
|
||||
#end
|
||||
}
|
||||
}
|
||||
|
||||
function set( o : Dynamic, f : String, v : Dynamic ) : Dynamic {
|
||||
if( o == null ) error(EInvalidAccess(f));
|
||||
Reflect.setProperty(o,f,v);
|
||||
return v;
|
||||
}
|
||||
|
||||
function fcall( o : Dynamic, f : String, args : Array<Dynamic> ) : Dynamic {
|
||||
return call(o, get(o, f), args);
|
||||
}
|
||||
|
||||
function call( o : Dynamic, f : Dynamic, args : Array<Dynamic> ) : Dynamic {
|
||||
return Reflect.callMethod(o,f,args);
|
||||
}
|
||||
|
||||
function cnew( cl : String, args : Array<Dynamic> ) : Dynamic {
|
||||
#if gdscript
|
||||
return null;
|
||||
#else
|
||||
var c = Type.resolveClass(cl);
|
||||
if( c == null ) c = resolve(cl);
|
||||
return Type.createInstance(c,args);
|
||||
#end
|
||||
}
|
||||
|
||||
}
|
||||
@@ -163,6 +163,7 @@ class Output {
|
||||
default:
|
||||
return parseHaxeExpression(buffer);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function parseHaxeExpression(buffer:HankBuffer):OutputType {
|
||||
|
||||
1742
hank/Parser.hx
Normal file
1742
hank/Parser.hx
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user