@@ -19,6 +19,7 @@ namespace _7Sharp.Intrerpreter
1919 using static TokenType ;
2020 public class Interpreter
2121 {
22+ internal Dictionary < string , FunctionDefinition > userFunctions = new Dictionary < string , FunctionDefinition > ( ) ;
2223 internal Dictionary < string , _7sFunction > functions = new Dictionary < string , _7sFunction > ( ) ;
2324 internal Stack < int > loopIndexes = new Stack < int > ( ) ;
2425 private ExpressionEvaluator evaluator = new ExpressionEvaluator ( ) ;
@@ -30,6 +31,7 @@ public class Interpreter
3031 public Interpreter ( )
3132 {
3233 InitEvaluator ( ) ;
34+ evaluator . PreEvaluateFunction += AddUserFunctions ;
3335 var built = LexerBuilder . BuildLexer < TokenType > ( ) ;
3436 if ( built . Errors . FindAll ( x => x . Level != sly . buildresult . ErrorLevel . WARN ) . Count != 0 )
3537 {
@@ -51,6 +53,26 @@ public Interpreter()
5153 }
5254 }
5355
56+ private void AddUserFunctions ( object sender , FunctionPreEvaluationEventArg e )
57+ {
58+ foreach ( var kv in userFunctions )
59+ {
60+ if ( kv . Key == e . Name )
61+ {
62+ if ( e . Args . Count == kv . Value . NumberOfArgs ( ) )
63+ {
64+ e . CancelEvaluation = false ;
65+ }
66+ else
67+ {
68+ WriteLineColor ( $ "{ e . Name } expects { kv . Value . NumberOfArgs ( ) } , but you put { e . Args . Count } ", Red ) ;
69+ e . CancelEvaluation = true ;
70+ }
71+ e . Value = kv . Value . Run ( e . EvaluateArgs ( ) ) ;
72+ }
73+ }
74+ }
75+
5476 private void InitEvaluator ( )
5577 {
5678 functions . Clear ( ) ;
@@ -61,14 +83,18 @@ private void InitEvaluator()
6183 {
6284 evaluator . Variables . Add ( f . Key , f . Value . Code ) ;
6385 }
86+ foreach ( ConsoleColor c in Enum . GetValues ( typeof ( ConsoleColor ) ) . Cast < ConsoleColor > ( ) )
87+ {
88+ evaluator . Variables . Add ( c . ToString ( ) , c ) ;
89+ }
6490 }
6591
6692 public void Run ( string code )
6793 {
6894 code = evaluator . RemoveComments ( code ) ; //just to make parsing easier
6995 try
7096 {
71- InternalRun ( code , true ) ;
97+ InternalRun ( code , out _ , true ) ;
7298 }
7399 catch ( Exception e )
74100 {
@@ -77,8 +103,16 @@ public void Run(string code)
77103 evaluator = new ExpressionEvaluator ( ) ;
78104 }
79105
80- private void InternalRun ( string code , bool reset = true )
106+ internal void InternalRun ( string code , out dynamic returnValue , bool reset = true , params KeyValuePair < string , dynamic > [ ] passedParams )
81107 {
108+ if ( passedParams != null && passedParams . Length > 0 )
109+ {
110+ foreach ( var kv in passedParams )
111+ {
112+ evaluator . Variables . Add ( kv . Key , kv . Value ) ;
113+ }
114+ }
115+ returnValue = null ;
82116 exitLoop = skipLoop = exit = false ;
83117 if ( exit )
84118 {
@@ -164,10 +198,30 @@ private void InternalRun(string code, bool reset = true)
164198 exitLoop = expression [ 0 ] . TokenID == BREAK ;
165199 skipLoop = ! exitLoop ;
166200 return ;
167- /*case RETURN:
168- break;*/
201+ case RETURN :
202+ expression = expression . Skip ( 1 ) . ToList ( ) ; //remove "return" keyword
203+ string expr = GetExpressionToToken ( expression , SEMICOLON ) ;
204+ try
205+ {
206+ returnValue = Evaluate ( expr ) ;
207+ }
208+ catch
209+ {
210+ returnValue = null ;
211+ }
212+ return ;
169213 }
170214 }
215+ else if ( IsFunctionDef ( expression ) )
216+ {
217+ string expr = GetExpressionToToken ( expression , LBRACE ) ;
218+ string [ ] args = GetArgs ( expr ) . Replace ( " " , string . Empty ) . Split ( new string [ ] { "," } , StringSplitOptions . RemoveEmptyEntries ) ;
219+ int end = GetClosingBrace ( tokens , i , out TokenList ts , out string inside ) ;
220+ bool returns = ts . FindIndex ( t => t . TokenID == RETURN ) > - 1 ;
221+ userFunctions . Add ( expression [ 1 ] . Value , new FunctionDefinition ( inside , this , args ) ) ;
222+ i = end ;
223+ continue ;
224+ }
171225 else if ( IsVarExpression ( expression ) )
172226 {
173227 string expr = GetExpressionToToken ( expression , SEMICOLON ) ;
@@ -200,7 +254,7 @@ private void InternalRun(string code, bool reset = true)
200254 loopIndexes . Push ( 0 ) ;
201255 for ( int j = 0 ; j < times && ! exitLoop ; j ++ )
202256 {
203- InternalRun ( inside , false ) ;
257+ InternalRun ( inside , out _ , false ) ;
204258 loopIndexes . Push ( loopIndexes . Pop ( ) + 1 ) ;
205259 skipLoop = false ;
206260 }
@@ -210,7 +264,7 @@ private void InternalRun(string code, bool reset = true)
210264 case WHILE :
211265 while ( ( bool ) Evaluate ( args ) && ! exitLoop )
212266 {
213- InternalRun ( inside , false ) ;
267+ InternalRun ( inside , out _ , false ) ;
214268 }
215269 break ;
216270 }
@@ -233,6 +287,25 @@ private void InternalRun(string code, bool reset = true)
233287 }
234288 i -- ;
235289 }
290+ if ( passedParams != null && passedParams . Length > 0 )
291+ {
292+ foreach ( var kv in passedParams )
293+ {
294+ evaluator . Variables . Remove ( kv . Key ) ;
295+ }
296+ }
297+ }
298+
299+ private bool IsFunctionDef ( TokenList expression )
300+ {
301+ bool result = false ;
302+ if ( expression . Count >= 3 )
303+ {
304+ result |= expression [ 0 ] . TokenID == FUNCTION ;
305+ result &= expression [ 1 ] . TokenID == IDENTIFIER ;
306+ result &= expression [ 2 ] . TokenID == LPAREN ;
307+ }
308+ return result ;
236309 }
237310
238311 private void ProcessIf ( TokenList expression , TokenList tokens , string code , ref int i )
@@ -259,7 +332,7 @@ private void ProcessIf(TokenList expression, TokenList tokens, string code, ref
259332 case IF :
260333 if ( ( bool ) Evaluate ( args ) )
261334 {
262- InternalRun ( inside , false ) ;
335+ InternalRun ( inside , out _ , false ) ;
263336 i = end ;
264337 }
265338 else
@@ -285,7 +358,7 @@ private void ProcessIf(TokenList expression, TokenList tokens, string code, ref
285358 break ;
286359 case ELSE :
287360 i = end ;
288- InternalRun ( inside , false ) ;
361+ InternalRun ( inside , out _ , false ) ;
289362 break ;
290363 }
291364 }
@@ -360,6 +433,10 @@ private string GetExpressionToToken(TokenList tokens, TokenType type)
360433 foreach ( var t in tokens )
361434 {
362435 expr += t . Value ;
436+ if ( new TokenType [ ] { FUNCTION , IF , ELSE , RETURN } . Contains ( t . TokenID ) )
437+ {
438+ expr += " " ;
439+ }
363440 }
364441 var ts = lexer . Tokenize ( expr ) . Tokens ;
365442 var f = ts . Find ( x => x . TokenID == type ) ;
0 commit comments