Refactor extend statement: remove unnecessary "as" keyword and push "this" variable context to the extend-statement scope
This commit is contained in:
@@ -11,7 +11,7 @@ import io.smnp.type.matcher.Matcher
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
object CustomMethod {
|
||||
fun create(type: Matcher, objectIdentifier: String, node: FunctionDefinitionNode): Method {
|
||||
fun create(type: Matcher, node: FunctionDefinitionNode): Method {
|
||||
val identifier = (node.identifier as IdentifierNode).token.rawValue
|
||||
|
||||
return object : Method(type, identifier) {
|
||||
@@ -23,7 +23,7 @@ object CustomMethod {
|
||||
new method signature body { env, obj, args ->
|
||||
val boundArguments =
|
||||
FunctionEnvironmentProvider.provideEnvironment(argumentsNode, args, env).toMutableMap()
|
||||
boundArguments[objectIdentifier] = obj
|
||||
boundArguments["this"] = obj
|
||||
|
||||
try {
|
||||
env.pushScope(boundArguments)
|
||||
|
||||
@@ -2,23 +2,18 @@ package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class ExtendNode(type: Node, identifier: Node, functions: Node, position: TokenPosition) : Node(3, position) {
|
||||
class ExtendNode(type: Node, functions: Node, position: TokenPosition) : Node(2, position) {
|
||||
operator fun component1(): Node = children[0]
|
||||
operator fun component2(): Node = children[1]
|
||||
operator fun component3(): Node = children[2]
|
||||
|
||||
val type: Node
|
||||
get() = children[0]
|
||||
|
||||
val identifier: Node
|
||||
get() = children[1]
|
||||
|
||||
val functions: Node
|
||||
get() = children[2]
|
||||
get() = children[1]
|
||||
|
||||
init {
|
||||
children[0] = type
|
||||
children[1] = identifier
|
||||
children[2] = functions
|
||||
children[1] = functions
|
||||
}
|
||||
}
|
||||
@@ -8,33 +8,38 @@ import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class ExtendParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
val simpleExtendParser = allOf(
|
||||
terminal(TokenType.EXTEND),
|
||||
assert(SingleTypeParser(), "type to be extended"),
|
||||
assert(terminal(TokenType.AS), "'as' keyword with identifier"),
|
||||
assert(SimpleIdentifierParser(), "identifier"),
|
||||
terminal(TokenType.WITH),
|
||||
assert(mapNode(FunctionDefinitionParser()) { BlockNode(Node.NONE, listOf(it), Node.NONE) }, "method definition")
|
||||
) { (extendToken, targetType, identifier, method) ->
|
||||
ExtendNode(targetType, identifier, method, extendToken.position)
|
||||
}
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
val simpleExtendParser = allOf(
|
||||
terminal(TokenType.EXTEND),
|
||||
assert(SingleTypeParser(), "type to be extended"),
|
||||
terminal(TokenType.WITH),
|
||||
assert(
|
||||
mapNode(FunctionDefinitionParser()) { BlockNode(Node.NONE, listOf(it), Node.NONE) },
|
||||
"method definition"
|
||||
)
|
||||
) { (extendToken, targetType, _, method) ->
|
||||
ExtendNode(targetType, method, extendToken.position)
|
||||
}
|
||||
|
||||
val complexExtendParser = allOf(
|
||||
terminal(TokenType.EXTEND),
|
||||
assert(SingleTypeParser(), "type to be extended"),
|
||||
assert(terminal(TokenType.AS), "'as' keyword with identifier"),
|
||||
assert(SimpleIdentifierParser(), "identifier"),
|
||||
assert(loop(terminal(TokenType.OPEN_CURLY), assert(FunctionDefinitionParser(), "method definition or }"), terminal(TokenType.CLOSE_CURLY)) {
|
||||
begin, methods, end -> BlockNode(begin, methods, end)
|
||||
}, "block with methods' definitions or 'with' keyword with single method definition")
|
||||
) { (extendToken, targetType, _, identifier, methods) ->
|
||||
ExtendNode(targetType, identifier, methods, extendToken.position)
|
||||
}
|
||||
val complexExtendParser = allOf(
|
||||
terminal(TokenType.EXTEND),
|
||||
assert(SingleTypeParser(), "type to be extended"),
|
||||
assert(
|
||||
loop(
|
||||
terminal(TokenType.OPEN_CURLY),
|
||||
assert(FunctionDefinitionParser(), "method definition or }"),
|
||||
terminal(TokenType.CLOSE_CURLY)
|
||||
) { begin, methods, end ->
|
||||
BlockNode(begin, methods, end)
|
||||
}, "block with methods' definitions or 'with' keyword with single method definition"
|
||||
)
|
||||
) { (extendToken, targetType, methods) ->
|
||||
ExtendNode(targetType, methods, extendToken.position)
|
||||
}
|
||||
|
||||
return oneOf(
|
||||
simpleExtendParser,
|
||||
complexExtendParser
|
||||
).parse(input)
|
||||
}
|
||||
return oneOf(
|
||||
simpleExtendParser,
|
||||
complexExtendParser
|
||||
).parse(input)
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,10 @@ package io.smnp.evaluation.evaluator
|
||||
|
||||
import io.smnp.callable.method.CustomMethod
|
||||
import io.smnp.callable.util.FunctionSignatureParser
|
||||
import io.smnp.dsl.ast.model.node.*
|
||||
import io.smnp.dsl.ast.model.node.ExtendNode
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionNode
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.dsl.ast.model.node.SingleTypeNode
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.PositionException
|
||||
@@ -13,12 +16,11 @@ class ExtendEvaluator : Evaluator() {
|
||||
override fun supportedNodes() = listOf(ExtendNode::class)
|
||||
|
||||
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
|
||||
val (typeNode, identifierNode, methodsNode) = node as ExtendNode
|
||||
val (typeNode, methodsNode) = node as ExtendNode
|
||||
val type = FunctionSignatureParser.matcherForSingleTypeNode(typeNode as SingleTypeNode)
|
||||
val identifier = (identifierNode as IdentifierNode).token.rawValue
|
||||
|
||||
methodsNode.children
|
||||
.map { it to CustomMethod.create(type, identifier, it as FunctionDefinitionNode) }
|
||||
.map { it to CustomMethod.create(type, it as FunctionDefinitionNode) }
|
||||
.forEach {
|
||||
try {
|
||||
environment.defineMethod(it.second)
|
||||
|
||||
@@ -14,7 +14,7 @@ function _flatten(list: list, output: list) {
|
||||
return output;
|
||||
}
|
||||
|
||||
extend list as this {
|
||||
extend list {
|
||||
function flatten() {
|
||||
return flatten(this);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
extend map as this {
|
||||
extend map {
|
||||
function containsKey(key) {
|
||||
return this.keys.contains(key);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
extend note as this {
|
||||
extend note {
|
||||
function withOctave(octave: int) {
|
||||
return Note(this.pitch, octave, this.duration.get("numerator"), this.duration.get("denominator"));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
extend string as this {
|
||||
extend string {
|
||||
function find(char: string) {
|
||||
if(char.length > 1) {
|
||||
throw "Only single character can act as a pattern to be found";
|
||||
|
||||
Reference in New Issue
Block a user