Refactor extend statement: remove unnecessary "as" keyword and push "this" variable context to the extend-statement scope

This commit is contained in:
2020-03-17 20:52:47 +01:00
parent 4cb234bdba
commit 70cb2e85bc
8 changed files with 47 additions and 45 deletions

View File

@@ -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)

View File

@@ -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
}
}

View File

@@ -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)
}
}

View File

@@ -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)

View File

@@ -14,7 +14,7 @@ function _flatten(list: list, output: list) {
return output;
}
extend list as this {
extend list {
function flatten() {
return flatten(this);
}

View File

@@ -1,4 +1,4 @@
extend map as this {
extend map {
function containsKey(key) {
return this.keys.contains(key);
}

View File

@@ -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"));
}

View File

@@ -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";