this repo has no description
at master 27 kB view raw
1namespace Astrid; 2 3public static class Interpreter 4{ 5 public static Token? Run(List<AST> block, Dictionary<string, (Types, Token)> Variables, Dictionary<string, (List<(string, Types)>, object, Types?)> Functions, string[] preAddedVars = null!, string[] preAddedFuncs = null!) 6 { 7 List<string> addedVars = new(); 8 if(preAddedVars != null) 9 addedVars.AddRange(preAddedVars.ToList()); 10 11 List<string> addedFuncs = new(); 12 if(preAddedFuncs != null) 13 addedFuncs.AddRange(preAddedFuncs.ToList()); 14 15 foreach(var ast in block) 16 { 17 if(ast.GetType() == typeof(ASTConditional)) 18 { 19 var call = (ASTConditional)ast; 20 var cond = RunExpression(call.condition, Variables, Functions); 21 22 if(cond.GetType() == typeof(TokenBoolean)) 23 { 24 var condbool = cond.value == "true"; 25 26 if(condbool) 27 { 28 var t = Run(call.block, Variables, Functions); 29 if(t != null) 30 { 31 Error.Throw("Can't use return in if condition", t); 32 } 33 } 34 } else 35 { 36 Error.Throw("Condition must be bool in if", cond); 37 } 38 } else if(ast.GetType() == typeof(ASTWhile)) 39 { 40 var call = (ASTWhile)ast; 41 var cond = RunExpression(call.condition, Variables, Functions); 42 43 if(cond.GetType() == typeof(TokenBoolean)) 44 { 45 var condbool = cond.value == "true"; 46 47 while(condbool) 48 { 49 cond = RunExpression(call.condition, Variables, Functions); 50 condbool = cond.value == "true"; 51 52 var t = Run(call.block, Variables, Functions); 53 if(t != null) 54 { 55 Error.Throw("Can't use return in while", t); 56 } 57 } 58 } else 59 { 60 Error.Throw("Condition must be bool in while", cond); 61 } 62 } else if(ast.GetType() == typeof(ASTMatch)) 63 { 64 var call = (ASTMatch)ast; 65 66 var toMatch = RunExpression(call.expr, Variables, Functions); 67 68 bool hasMatched = false; 69 70 call.matches.ToList().ForEach(e => { 71 bool hasRunDefault = false; 72 73 if(e.Key.expression[0] is TokenIdentifier id) 74 { 75 if(id.value == "_") 76 { 77 if(e.Key.expression.Count > 1) 78 { 79 Error.Throw("Default match can't have more expressions!", id); 80 } 81 82 hasRunDefault = true; 83 if(!hasMatched) 84 { 85 Run(e.Value, Variables, Functions); 86 } 87 } 88 } 89 90 if(!hasRunDefault) 91 { 92 var result = RunExpression(e.Key, Variables, Functions); 93 94 if(Parser.GetTypeFromValue(toMatch) != Parser.GetTypeFromValue(result)) 95 { 96 Error.Throw($"Can't match {result} to {toMatch}", result); 97 } 98 99 if(toMatch.value == result.value) 100 { 101 hasMatched = true; 102 Run(e.Value, Variables, Functions); 103 } 104 } 105 }); 106 } else if(ast.GetType() == typeof(ASTFunctionCall)) 107 { 108 var call = (ASTFunctionCall)ast; 109 110 RunFunction(call, Variables, Functions); 111 } else if(ast.GetType() == typeof(ASTFunctionDefine)) 112 { 113 var call = (ASTFunctionDefine)ast; 114 115 addedFuncs.Add(call.label); 116 117 Functions.Add(call.label, ( 118 call.parameters, 119 call.block, 120 call.returnType 121 )); 122 } else if(ast.GetType() == typeof(ASTReturn)) 123 { 124 var call = (ASTReturn)ast; 125 126 return RunExpression(call.expression, Variables, Functions); 127 } else if(ast.GetType() == typeof(ASTVariableDefine)) 128 { 129 var call = (ASTVariableDefine)ast; 130 131 Variables.Add(call.label, (call.type, RunExpression(call.value, Variables, Functions))); 132 addedVars.Add(call.label); 133 } else if(ast is ASTVariableReassign call) 134 { 135 var value = RunExpression(call.value, Variables, Functions); 136 Types type = Types.Int; 137 138 // Console.WriteLine("reached as"); 139 140 if(!Variables.Keys.Contains(call.label)) 141 throw new Exception($"Variable {call.label} doens't exist so it can't be reassigned"); 142 143 switch(Variables[call.label].Item1) 144 { 145 case Types.Int: 146 if(value.GetType() != typeof(TokenInt)) 147 Error.Throw($"Cannot assign ${value.GetType()} to int", value); 148 type = Types.Int; 149 break; 150 case Types.Float: 151 if(value.GetType() != typeof(TokenFloat)) 152 Error.Throw($"Cannot assign ${value.GetType()} to float", value); 153 type = Types.Float; 154 break; 155 case Types.String: 156 if(value.GetType() != typeof(TokenString)) 157 Error.Throw($"Cannot assign ${value.GetType()} to string", value); 158 type = Types.String; 159 break; 160 default: 161 Error.Throw($"Invalid type in reassign {Variables[call.label].Item1}", Variables[call.label].Item2); break; 162 } 163 164 switch(call.asop) 165 { 166 case AssignOp.Assign: { 167 Variables[call.label] = (type, value); 168 } break; 169 case AssignOp.Plus: { 170 switch(type) 171 { 172 case Types.Int: { 173 Variables[call.label] = (type, new TokenInt((int.Parse(Variables[call.label].Item2.value) + int.Parse(value.value)).ToString(), value.lineStart, value.lineEnd, value.charStart, value.charEnd)); 174 } break; 175 case Types.Float: { 176 Variables[call.label] = (type, new TokenFloat((float.Parse(Variables[call.label].Item2.value) + float.Parse(value.value)).ToString(), value.lineStart, value.lineEnd, value.charStart, value.charEnd)); 177 } break; 178 case Types.String: { 179 Variables[call.label] = (type, new TokenString(Variables[call.label].Item2.value + value.value, value.lineStart, value.lineEnd, value.charStart, value.charEnd)); 180 } break; 181 } 182 } break; 183 case AssignOp.Minus: { 184 switch(type) 185 { 186 case Types.Int: { 187 Variables[call.label] = (type, new TokenInt((int.Parse(Variables[call.label].Item2.value) - int.Parse(value.value)).ToString(), value.lineStart, value.lineEnd, value.charStart, value.charEnd)); 188 } break; 189 case Types.Float: { 190 Variables[call.label] = (type, new TokenFloat((float.Parse(Variables[call.label].Item2.value) - float.Parse(value.value)).ToString(), value.lineStart, value.lineEnd, value.charStart, value.charEnd)); 191 } break; 192 default: { 193 Error.Throw($"Can't use operator minus with {type}", Variables[call.label].Item2); 194 } break; 195 } 196 } break; 197 case AssignOp.Multiply: { 198 switch(type) 199 { 200 case Types.Int: { 201 Variables[call.label] = (type, new TokenInt((int.Parse(Variables[call.label].Item2.value) * int.Parse(value.value)).ToString(), value.lineStart, value.lineEnd, value.charStart, value.charEnd)); 202 } break; 203 case Types.Float: { 204 Variables[call.label] = (type, new TokenFloat((float.Parse(Variables[call.label].Item2.value) * float.Parse(value.value)).ToString(), value.lineStart, value.lineEnd, value.charStart, value.charEnd)); 205 } break; 206 default: { 207 Error.Throw($"Can't use operator multiply with {type}", Variables[call.label].Item2); 208 } break; 209 } 210 } break; 211 case AssignOp.Divide: { 212 switch(type) 213 { 214 case Types.Int: { 215 Variables[call.label] = (type, new TokenInt((int.Parse(Variables[call.label].Item2.value) / int.Parse(value.value)).ToString(), value.lineStart, value.lineEnd, value.charStart, value.charEnd)); 216 } break; 217 case Types.Float: { 218 Variables[call.label] = (type, new TokenFloat((float.Parse(Variables[call.label].Item2.value) / float.Parse(value.value)).ToString(), value.lineStart, value.lineEnd, value.charStart, value.charEnd)); 219 } break; 220 default: { 221 Error.Throw($"Can't use operator divide with {type}", Variables[call.label].Item2); 222 } break; 223 } 224 } break; 225 case AssignOp.Power: { 226 switch(type) 227 { 228 case Types.Int: { 229 Variables[call.label] = (type, new TokenInt(Math.Pow(int.Parse(Variables[call.label].Item2.value), int.Parse(value.value)).ToString(), value.lineStart, value.lineEnd, value.charStart, value.charEnd)); 230 } break; 231 case Types.Float: { 232 Variables[call.label] = (type, new TokenFloat(Math.Pow(float.Parse(Variables[call.label].Item2.value), float.Parse(value.value)).ToString(), value.lineStart, value.lineEnd, value.charStart, value.charEnd)); 233 } break; 234 default: { 235 Error.Throw($"Can't use operator power with {type}", Variables[call.label].Item2); 236 } break; 237 } 238 } break; 239 case AssignOp.Modulo: { 240 switch(type) 241 { 242 case Types.Int: { 243 Variables[call.label] = (type, new TokenInt((int.Parse(Variables[call.label].Item2.value) % int.Parse(value.value)).ToString(), value.lineStart, value.lineEnd, value.charStart, value.charEnd)); 244 } break; 245 case Types.Float: { 246 Variables[call.label] = (type, new TokenFloat((float.Parse(Variables[call.label].Item2.value) % float.Parse(value.value)).ToString(), value.lineStart, value.lineEnd, value.charStart, value.charEnd)); 247 } break; 248 default: { 249 Error.Throw($"Can't use operator modulo with {type}", Variables[call.label].Item2); 250 } break; 251 } 252 } break; 253 } 254 } 255 } 256 257 foreach(var d in addedVars) 258 { 259 Variables.Remove(d); 260 } 261 262 foreach(var d in addedFuncs) 263 { 264 Functions.Remove(d); 265 } 266 267 return null; 268 } 269 270 public static Token? RunFunction(ASTFunctionCall fc, Dictionary<string, (Types, Token)> Variables, Dictionary<string, (List<(string, Types)>, object, Types?)> Functions) 271 { 272 if(!Functions.Keys.Contains(fc.label)) 273 { 274 Error.Throw("Function doesn't exist", new(0, 0, 0, 0)); 275 } 276 277 // fc.value.ToList().ForEach(e => Console.WriteLine(e.Key)); 278 // Functions[fc.label].Item1.ForEach(e => Console.WriteLine(e.Item1)); 279 280 foreach(var i in fc.value) 281 { 282 bool contains = false; 283 Functions[fc.label].Item1.ForEach(e => { 284 if(!contains) 285 contains = e.Item1 == i.Key; 286 }); 287 // if(!contains) 288 // { 289 // Error.Throw($"Parameter {i.Key} isn't satisifed", new(0, 0, 0, 0)); 290 // } 291 } 292 293 // Functions[fc.label] 294 295 if(Functions[fc.label].Item2 is List<AST> block) 296 { 297 string[] preAdd = fc.value.Keys.ToArray(); 298 299 fc.value.ToList().ForEach(e => { 300 var Tok = RunExpression(e.Value, Variables, Functions); 301 Variables.Add(e.Key, (Parser.GetTypeFromValue(Tok), Tok)); 302 }); 303 return Run(block, Variables, Functions, preAdd); 304 } else 305 { 306 var asd = (dynamic message) => {}; 307 308 List<Token> parameters = fc.value.Select(e => RunExpression(e.Value, Variables, Functions)).ToList(); 309 310 if(parameters.Count < Functions[fc.label].Item1.Count) 311 { 312 Error.Throw($"Parameters aren't satisifed in {fc.label}", new(0, 0, 0, 0)); 313 } 314 315 var val = ((dynamic)Functions[fc.label].Item2).Invoke(parameters); 316 return val; 317 } 318 } 319 320 321 public static Token RunExpression(ASTExpression _expr, Dictionary<string, (Types, Token)> Variables, Dictionary<string, (List<(string, Types)>, object, Types?)> Functions) 322 { 323 List<object> tokensOld = _expr.expression; 324 325 // Console.WriteLine("a"); 326 // foreach(var i in tokensOld) 327 // { 328 // Console.WriteLine(i); 329 // } 330 331 List<Token> tokens = new(); 332 333 foreach(var tok in tokensOld) 334 { 335 if(tok.GetType() != typeof(ASTFunctionCall)) 336 { 337 tokens.Add((Token)tok); 338 } else 339 { 340 // Console.WriteLine("func call"); 341 var val = RunFunction((ASTFunctionCall)tok, Variables, Functions); 342 if(val == null && Functions[((ASTFunctionCall)tok).label].Item3 != null) 343 { 344 Error.Throw($"Return type must be {Functions[((ASTFunctionCall)tok).label].Item3}", new(0, 0, 0, 0)); 345 } else if(Parser.GetTypeFromValue(val!) != Functions[((ASTFunctionCall)tok).label].Item3) 346 { 347 Error.Throw($"Return type must be {Functions[((ASTFunctionCall)tok).label].Item3}", val!); 348 } 349 if(val == null) 350 Error.Throw(((ASTFunctionCall)tok).label, default(Token)!); 351 352 tokens.Add(val!); 353 } 354 } 355 356 // foreach(var i in tokens) 357 // { 358 // Console.WriteLine("tok " + Tokenizer.GetTokenAsHuman(i)); 359 // } 360 361 List<Token> stack = new(); 362 var token = tokens[0]; 363 364 while(tokens.Count > 0) 365 { 366 token = tokens[0]; 367 tokens = tokens.Skip(1).ToList(); 368 369 // Console.WriteLine("Intepret " + token); 370 371 if(Parser.ExprValues.Contains(token.GetType())) 372 { 373 if(token.GetType() != typeof(TokenIdentifier)) 374 stack.Add(token); 375 else { 376 // Console.WriteLine("Id " + token.value + " to " + Tokenizer.GetTokenAsHuman(variables[token.value])); 377 stack.Add(Variables[token.value].Item2); 378 } 379 } else if(Parser.ExprOperators.Keys.Contains(token.GetType())) 380 { 381 if(new [] {typeof(TokenEquals), typeof(TokenNotEquals), typeof(TokenGreater), typeof(TokenGreaterEquals), typeof(TokenLesser), typeof(TokenLesserEquals)}.Contains(token.GetType())) { 382 if(stack.Count < 2) 383 throw new Exception("Stack doesn't contains two values"); 384 385 Token left = stack[stack.Count - 2]; 386 Token right = stack[stack.Count - 1]; 387 388 if(left.GetType() == right.GetType()) 389 { 390 string value = ""; 391 if(token.GetType() == typeof(TokenEquals)) 392 { 393 value = (left.value == right.value).ToString().ToLower(); 394 } else if(token.GetType() == typeof(TokenNotEquals)) 395 { 396 value = (left.value != right.value).ToString().ToLower(); 397 } else if(token.GetType() == typeof(TokenGreater)) 398 { 399 if(!new [] {typeof(TokenInt), typeof(TokenFloat)}.Contains(left.GetType()) || !new [] {typeof(TokenInt), typeof(TokenFloat)}.Contains(right.GetType())) 400 Error.Throw($"Cannot apply greater than to non int or float type, {Tokenizer.GetTokenAsHuman(left)}, {Tokenizer.GetTokenAsHuman(right)}", left); 401 402 value = (float.Parse(left.value) > float.Parse(right.value)).ToString().ToLower(); 403 } else if(token.GetType() == typeof(TokenGreaterEquals)) 404 { 405 if(!new [] {typeof(TokenInt), typeof(TokenFloat)}.Contains(left.GetType()) || !new [] {typeof(TokenInt), typeof(TokenFloat)}.Contains(right.GetType())) 406 Error.Throw($"Cannot apply greaterequals than to non int or float type, {Tokenizer.GetTokenAsHuman(left)}, {Tokenizer.GetTokenAsHuman(right)}", left); 407 408 value = (float.Parse(left.value) >= float.Parse(right.value)).ToString().ToLower(); 409 } else if(token.GetType() == typeof(TokenLesser)) 410 { 411 if(!new [] {typeof(TokenInt), typeof(TokenFloat)}.Contains(left.GetType()) || !new [] {typeof(TokenInt), typeof(TokenFloat)}.Contains(right.GetType())) 412 Error.Throw($"Cannot apply lesser than to non int or float type, {Tokenizer.GetTokenAsHuman(left)}, {Tokenizer.GetTokenAsHuman(right)}", left); 413 414 value = (float.Parse(left.value) < float.Parse(right.value)).ToString().ToLower(); 415 } else if(token.GetType() == typeof(TokenLesserEquals)) 416 { 417 if(!new [] {typeof(TokenInt), typeof(TokenFloat)}.Contains(left.GetType()) || !new [] {typeof(TokenInt), typeof(TokenFloat)}.Contains(right.GetType())) 418 Error.Throw($"Cannot apply lesserequals than to non int or float type, {Tokenizer.GetTokenAsHuman(left)}, {Tokenizer.GetTokenAsHuman(right)}", left); 419 420 value = (float.Parse(left.value) <= float.Parse(right.value)).ToString().ToLower(); 421 } 422 423 stack.Add(new TokenBoolean(value, left.lineStart, left.lineEnd, left.charStart, left.charEnd)); 424 stack.RemoveAt(stack.Count - 2); 425 stack.RemoveAt(stack.Count - 2); 426 } else 427 { 428 //Console.WriteLine("expr"); 429 Error.Throw($"Types don't match in expression equals. Matching left: {left.GetType()}, right: {right.GetType()}", left); 430 } 431 } else if(Parser.ExprOperatorsAlgebraic.Keys.Contains(token.GetType())) 432 { 433 if(stack.Count < 2) 434 Error.Throw("Stack doesn't contain two values", token); 435 436 Token left = stack[stack.Count - 2]; 437 Token right = stack[stack.Count - 1]; 438 439 if(left.GetType() == typeof(TokenInt) && right.GetType() == typeof(TokenInt)) 440 { 441 string value = ""; 442 // Console.Write("int "); 443 if(token.GetType() == typeof(TokenPlus)) 444 { 445 // Console.WriteLine($"{int.Parse(left.value)} + {int.Parse(right.value)}"); 446 value = (int.Parse(left.value) + int.Parse(right.value)).ToString().ToLower(); 447 } else if(token.GetType() == typeof(TokenMinus)) 448 { 449 // Console.WriteLine($"{int.Parse(left.value)} - {int.Parse(right.value)}"); 450 value = (int.Parse(left.value) - int.Parse(right.value)).ToString().ToLower(); 451 } else if(token.GetType() == typeof(TokenDivide)) 452 { 453 // Console.WriteLine($"{int.Parse(left.value)} / {int.Parse(right.value)}"); 454 value = (int.Parse(left.value) / int.Parse(right.value)).ToString().ToLower(); 455 } else if(token.GetType() == typeof(TokenMultiply)) 456 { 457 // Console.WriteLine($"{int.Parse(left.value)} * {int.Parse(right.value)}"); 458 value = (int.Parse(left.value) * int.Parse(right.value)).ToString().ToLower(); 459 } else if(token.GetType() == typeof(TokenPower)) 460 { 461 // Console.WriteLine($"{int.Parse(left.value)} ^ {int.Parse(right.value)}"); 462 value = ((int)Math.Pow(int.Parse(left.value), int.Parse(right.value))).ToString().ToLower(); 463 } else if(token.GetType() == typeof(TokenModulo)) 464 { 465 // Console.WriteLine($"{int.Parse(left.value)} ^ {int.Parse(right.value)}"); 466 value = (int.Parse(left.value) % int.Parse(right.value)).ToString().ToLower(); 467 } 468 469 // Console.WriteLine("final value: " + value); 470 stack.Add(new TokenInt(value, left.lineStart, left.lineEnd, left.charStart, left.charEnd)); 471 stack.RemoveAt(stack.Count - 2); 472 stack.RemoveAt(stack.Count - 2); 473 } else if(left.GetType() == typeof(TokenFloat) && right.GetType() == typeof(TokenFloat)) 474 { 475 string value = ""; 476 // Console.Write("float "); 477 if(token.GetType() == typeof(TokenPlus)) 478 { 479 // Console.WriteLine($"{int.Parse(left.value)} + {int.Parse(right.value)}"); 480 value = (float.Parse(left.value) + float.Parse(right.value)).ToString().ToLower(); 481 } else if(token.GetType() == typeof(TokenMinus)) 482 { 483 // Console.WriteLine($"{int.Parse(left.value)} - {int.Parse(right.value)}"); 484 value = (float.Parse(left.value) - float.Parse(right.value)).ToString().ToLower(); 485 } else if(token.GetType() == typeof(TokenDivide)) 486 { 487 // Console.WriteLine($"{int.Parse(left.value)} / {int.Parse(right.value)}"); 488 value = (float.Parse(left.value) / float.Parse(right.value)).ToString().ToLower(); 489 } else if(token.GetType() == typeof(TokenMultiply)) 490 { 491 // Console.WriteLine($"{int.Parse(left.value)} * {int.Parse(right.value)}"); 492 value = (float.Parse(left.value) * float.Parse(right.value)).ToString().ToLower(); 493 } else if(token.GetType() == typeof(TokenPower)) 494 { 495 // Console.WriteLine($"{int.Parse(left.value)} ^ {int.Parse(right.value)}"); 496 value = ((float)Math.Pow(float.Parse(left.value), float.Parse(right.value))).ToString().ToLower(); 497 } else if(token.GetType() == typeof(TokenModulo)) 498 { 499 // Console.WriteLine($"{int.Parse(left.value)} * {int.Parse(right.value)}"); 500 value = (float.Parse(left.value) % float.Parse(right.value)).ToString().ToLower(); 501 } 502 503 // Console.WriteLine("final value: " + value); 504 stack.Add(new TokenFloat(value, left.lineStart, left.lineEnd, left.charStart, left.charEnd)); 505 stack.RemoveAt(stack.Count - 2); 506 stack.RemoveAt(stack.Count - 2); 507 } else if(left.GetType() == typeof(TokenString) && right.GetType() == typeof(TokenString)) 508 { 509 string value = ""; 510 // Console.Write("float "); 511 if(token.GetType() == typeof(TokenPlus)) 512 { 513 // Console.WriteLine($"{int.Parse(left.value)} + {int.Parse(right.value)}"); 514 value = left.value + right.value; 515 } else 516 { 517 Error.Throw($"Can't use operator {token.GetType()} with string", token); 518 } 519 520 // Console.WriteLine("final value: " + value); 521 stack.Add(new TokenString(value, left.lineStart, left.lineEnd, left.charStart, left.charEnd)); 522 stack.RemoveAt(stack.Count - 2); 523 stack.RemoveAt(stack.Count - 2); 524 } else 525 { 526 Error.Throw($"Types don't match in expression equals. Matching left: {left.GetType()}, right: {right.GetType()}", left); 527 } 528 } 529 } 530 } 531 532 if(stack.Count > 1) 533 { 534 string st = "Stack exited longer than 1 "; 535 stack.ForEach(e => st += Tokenizer.GetTokenAsHuman(e)); 536 Error.Throw(st, token); 537 } 538 539 return stack[0]; 540 } 541}