Add 'throw' statement

This commit is contained in:
Bartłomiej Pluta
2019-07-13 14:48:58 +02:00
parent a07b226edb
commit 86cf5d01f3
7 changed files with 52 additions and 2 deletions

View File

@@ -10,12 +10,14 @@ def StatementParser(input):
from smnp.ast.node.block import BlockParser from smnp.ast.node.block import BlockParser
from smnp.ast.node.condition import IfElseStatementParser from smnp.ast.node.condition import IfElseStatementParser
from smnp.ast.node.expression import ExpressionParser from smnp.ast.node.expression import ExpressionParser
from smnp.ast.node.ret import ReturnParser from smnp.ast.node.ret import ReturnParser
from smnp.ast.node.throw import ThrowParser
return Parser.oneOf( return Parser.oneOf(
IfElseStatementParser, IfElseStatementParser,
ExpressionParser, ExpressionParser,
BlockParser, BlockParser,
ReturnParser, ReturnParser,
ThrowParser,
name="statement" name="statement"
)(input) )(input)

17
smnp/ast/node/throw.py Normal file
View File

@@ -0,0 +1,17 @@
from smnp.ast.node.expression import ExpressionParser
from smnp.ast.node.valuable import Valuable
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Throw(Valuable):
pass
def ThrowParser(input):
return Parser.allOf(
Parser.terminal(TokenType.THROW),
Parser.doAssert(ExpressionParser, "error message as string"),
createNode=lambda throw, message: Throw.withValue(message, throw.pos),
name="throw"
)(input)

9
smnp/error/custom.py Normal file
View File

@@ -0,0 +1,9 @@
from smnp.error.base import SmnpException
class CustomException(SmnpException):
def __init__(self, message, pos):
super().__init__(message, pos)
def _title(self):
return "Execution Error"

View File

@@ -5,6 +5,7 @@ from smnp.ast.node.function import FunctionDefinition
from smnp.ast.node.imports import Import from smnp.ast.node.imports import Import
from smnp.ast.node.program import Program from smnp.ast.node.program import Program
from smnp.ast.node.ret import Return from smnp.ast.node.ret import Return
from smnp.ast.node.throw import Throw
from smnp.error.runtime import RuntimeException from smnp.error.runtime import RuntimeException
from smnp.type.model import Type from smnp.type.model import Type
@@ -69,7 +70,6 @@ class EvaluationResult():
def evaluate(node, environment): def evaluate(node, environment):
from smnp.runtime.evaluators.program import ProgramEvaluator from smnp.runtime.evaluators.program import ProgramEvaluator
from smnp.runtime.evaluators.expression import expressionEvaluator from smnp.runtime.evaluators.expression import expressionEvaluator
from smnp.runtime.evaluators.condition import IfElseStatementEvaluator from smnp.runtime.evaluators.condition import IfElseStatementEvaluator
from smnp.runtime.evaluators.block import BlockEvaluator from smnp.runtime.evaluators.block import BlockEvaluator
@@ -77,6 +77,8 @@ def evaluate(node, environment):
from smnp.runtime.evaluators.function import FunctionDefinitionEvaluator from smnp.runtime.evaluators.function import FunctionDefinitionEvaluator
from smnp.runtime.evaluators.function import ReturnEvaluator from smnp.runtime.evaluators.function import ReturnEvaluator
from smnp.runtime.evaluators.extend import ExtendEvaluator from smnp.runtime.evaluators.extend import ExtendEvaluator
from smnp.runtime.evaluators.throw import ThrowEvaluator
result = Evaluator.oneOf( result = Evaluator.oneOf(
Evaluator.forNodes(ProgramEvaluator.evaluate, Program), Evaluator.forNodes(ProgramEvaluator.evaluate, Program),
Evaluator.forNodes(IfElseStatementEvaluator.evaluate, IfElse), Evaluator.forNodes(IfElseStatementEvaluator.evaluate, IfElse),
@@ -85,6 +87,7 @@ def evaluate(node, environment):
Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinition), Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinition),
Evaluator.forNodes(ReturnEvaluator.evaluate, Return), Evaluator.forNodes(ReturnEvaluator.evaluate, Return),
Evaluator.forNodes(ExtendEvaluator.evaluate, Extend), Evaluator.forNodes(ExtendEvaluator.evaluate, Extend),
Evaluator.forNodes(ThrowEvaluator.evaluate, Throw),
#Evaluator.forNodes(ImportEvaluator.evaluate, ImportNode), #Evaluator.forNodes(ImportEvaluator.evaluate, ImportNode),
#Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinitionNode), #Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinitionNode),
#Evaluator.forNodes(ExtendEvaluator.evaluate, ExtendNode), #Evaluator.forNodes(ExtendEvaluator.evaluate, ExtendNode),

View File

@@ -0,0 +1,17 @@
from smnp.error.custom import CustomException
from smnp.error.runtime import RuntimeException
from smnp.runtime.evaluator import Evaluator
from smnp.runtime.evaluators.expression import expressionEvaluator
from smnp.type.model import Type
class ThrowEvaluator(Evaluator):
@classmethod
def evaluator(cls, node, environment):
string = expressionEvaluator(doAssert=True)(node.value, environment).value
if string.type != Type.STRING:
raise RuntimeException(f"Only {Type.STRING.name.lower()} types can be thrown", node.value.pos)
raise CustomException(string.value, node.pos)

View File

@@ -50,6 +50,7 @@ tokenizers = (
separated(defaultTokenizer(TokenType.RETURN)), separated(defaultTokenizer(TokenType.RETURN)),
separated(defaultTokenizer(TokenType.EXTEND)), separated(defaultTokenizer(TokenType.EXTEND)),
separated(defaultTokenizer(TokenType.IMPORT)), separated(defaultTokenizer(TokenType.IMPORT)),
separated(defaultTokenizer(TokenType.THROW)),
separated(defaultTokenizer(TokenType.FROM)), separated(defaultTokenizer(TokenType.FROM)),
separated(defaultTokenizer(TokenType.WITH)), separated(defaultTokenizer(TokenType.WITH)),
separated(defaultTokenizer(TokenType.ELSE)), separated(defaultTokenizer(TokenType.ELSE)),

View File

@@ -35,6 +35,7 @@ class TokenType(Enum):
RETURN = 'return' RETURN = 'return'
EXTEND = 'extend' EXTEND = 'extend'
IMPORT = 'import' IMPORT = 'import'
THROW = 'throw'
FROM = 'from' FROM = 'from'
WITH = 'with' WITH = 'with'
ELSE = 'else' ELSE = 'else'