public ProgramContext Parse(string text, ICompiler compiler, BlockMode blockMode) { this.compiler = compiler; this.blockMode = blockMode; tokenizer = new Tokenizer(text); tokenizer.Tokenize(); tokens = tokenizer.tokens; foreach (var t in tokenizer.tokens) { Console.WriteLine(t); } var mfc = new FunctionContext(); mfc.name = "main"; var output = new BlockContext() { parent = mfc }; TypedContext t2 = null; while ((t2 = GetContext(mfc, 0, 0, 0)) != null) { output.body.Add(t2); } if (output is BlockContext) { mfc.body = output as BlockContext; } else { mfc.body = new BlockContext() { parent = mfc, body = { output } }; } var mcc = new ClassContext(); mcc.name = "init"; mcc.functions.Add(mfc); mfc.parent = mcc; var pc = new ProgramContext(); pc.name = "test"; pc.classes.Add(mcc); mcc.parent = pc; pc.main = mfc; return(pc); }
private void OnExitClicked() { TypedContext.ChangeState(); }
private void OnLoginClicked() { TypedContext.TryLogin(_loginField.text, _passwordField.text); }
private string GenCode(TypedContext context) { if (context is BlockContext) { string ret = "{"; string oldIndent = indent; indent += "\t"; (context as BlockContext).body.ForEach(a => ret += indent + GenCode(a) + ';'); indent = oldIndent; return(ret += indent + "}"); } else if (context is FunctionContext) { var c = context as FunctionContext; string ret = ""; string oldIndent = indent; indent += "\t"; if (c.body is BlockContext) { var body = c.body as BlockContext; for (int i = 0; i < body.body.Count - 1; i++) { ret += indent + GenCode(body.body[i]) + ';'; } ret += indent + (c.type == "sys.void" || (c.parent.parent as ProgramContext).main == c ? "" : "return ") + GenCode(body.body.Last()) + ';'; } indent = oldIndent; return(ret); } else if (context is BreakContext) { return("break"); } else if (context is StaticTypeContext) { var c = context as StaticTypeContext; return(c.type); } else if (context is ArrayInitContext) { var c = context as ArrayInitContext; return($"new {ToCsString(ToCsType(c.type).GetElementType())}[{GenCode(c.length)}]"); } else if (context is ListContext) { var c = context as ListContext; var ret = $"new {ToCsString(ToCsType(c.type))}()"; if (c.content.Count > 0) { ret += $" {{{c.content.Select(c => GenCode(c)).AddCommas()}}}"; } return(ret); } else if (context is MemberContext) { var c = context as MemberContext; return($"{GenCode(c.owner)}.{c.memberName}"); } else if (context is CallContext) { var c = context as CallContext; switch (c.methodName) { case "_getIndex": return($"{GenCode(c.owner)}[{c.arguments.Select(a => GenCode(a)).AddCommas()}]"); case "_setIndex": return($"{GenCode(c.owner)}[{c.arguments.SkipLast(1).Select(a => GenCode(a)).AddCommas()}] = {GenCode(c.arguments.Last())}"); } string args = c.arguments.Select(a => GenCode(a)).AddCommas(); switch (c.owner.type.Before("<") + '.' + c.methodName) { case "sys.object.hash": return($"{GenCode(c.owner)}.GetHashCode()"); case "sys.object.toStr": return($"{GenCode(c.owner)}.ToString()"); case "sys.string.upper": return($"{GenCode(c.owner)}.ToUpper()"); case "sys.string.lower": return($"{GenCode(c.owner)}.ToLower()"); case "sys.string.sub": return($"{GenCode(c.owner)}.Substring({args})"); case "sys.string.split": return($"{GenCode(c.owner)}.Split({args})"); case "sys.string.replace": return($"{GenCode(c.owner)}.Replace({args})"); case "sys.string.find": return($"{GenCode(c.owner)}.IndexOf({args}"); case "sys.list.add": return($"{GenCode(c.owner)}.Add({args})"); case "sys.list.remove": return($"{GenCode(c.owner)}.Remove({args})"); case "sys.list.len": return($"{GenCode(c.owner)}.Count"); case "sys.arr.len": return($"{GenCode(c.owner)}.Length"); case "sys.rand.nextInt": return($"Dependencies.RandInt({args})"); case "sys.console.print": return($"System.Console.Write({args})"); case "sys.console.println": return($"System.Console.WriteLine({args})"); case "sys.console.readln": return("System.Console.ReadLine()"); case "sys.console.wait": return("System.Console.ReadKey()"); case "sys.console.clear": return("System.Console.Clear()"); } return($"{GenCode(c.owner)}.{c.methodName}({args})"); } else if (context is FromContext) { var c = context as FromContext; return($"{GenCode(c.reference)} in {GenCode(c.body)}"); } else if (context is IfContext) { var c = context as IfContext; return($"if({GenCode(c.condition)}) {GenCode(c.body)}"); } else if (context is ElseContext) { var c = context as ElseContext; var prev = GenCode(c.chainParent); if (prev.Last() != '}') { prev += ';'; } return($"{prev} else {GenCode(c.body)}"); } else if (context is LoopContext) { var c = context as LoopContext; if (c.condition is FromContext) { return($"foreach({GenCode(c.condition)}) {GenCode(c.body)}"); } else if (c.condition.type == SysLib.BoolType.name) { return($"while({GenCode(c.condition)}) {GenCode(c.body)}"); } return($"for({GenCode(c.condition)}) {GenCode(c.body)}"); } else if (context is AssignContext) { var c = context as AssignContext; return(GenCode(c.variable) + " = " + GenCode(c.value)); } else if (context is VarDecContext) { var c = context as VarDecContext; return($"{ToCsString(ToCsType(c.type))} {c.name}"); } else if (context is ArrayContext) { var c = context as ArrayContext; var ret = $"new {ToCsString(ToCsType(c.type))} {{"; foreach (var e in c.content) { ret += GenCode(e) + ", "; } ret = ret.Substring(0, ret.Length - 2) + '}'; return(ret); } else if (context is VarContext) { var c = context as VarContext; return(c.variable.name); } else if (context is ParenContext) { var c = context as ParenContext; return($"({GenCode(c.interior)})"); } else if (context is ConstContext) { var c = context as ConstContext; if (c.type == "sys.string") { return($"\"{c.value}\""); } if (c.type == "sys.char") { return($"'{c.value}'"); } if (c.type == "sys.bool") { return(c.value.ToString().ToLower()); } return(c.value.ToString()); } else if (context is ConvertContext) { var c = context as ConvertContext; return(GenCode(c.interior)); } else if (context is SimpleOpContext) { var c = context as SimpleOpContext; return(c.op + GenCode(c.a)); } else if (context is OpContext) { var c = context as OpContext; if (c.op == "->") { return($"Dependencies.To({GenCode(c.a)},{GenCode(c.b)})"); } return(GenCode(c.a) + " " + c.op + " " + GenCode(c.b)); } return(null); }
private TypedContext GetContext(IScopeOwner context, int opDepth, int callDepth, int flags) { tokenizer.advance(0); var s0 = tokenizer.peekNext().value; TypedContext ret = null; //number if (int.TryParse(s0, out int unused) && tokenizer.peekNext().value == "." && float.TryParse(tokenizer.peekNext().value, out float num)) { tokenizer.advance(2); s0 += "." + num; } else { tokenizer.advance(0); tokenizer.peekNext(); } //parenthesis if (s0 == "") { tokenizer.advance(0); return(null); } else if (s0 == "(") { if (tokenizer.peekNext().value == ")") { ret = new ParenContext() { parent = context }; tokenizer.advance(1); } else { tokenizer.advance(1); var t1 = GetContext(context, 0, 0, NoBlocks); var sn1 = tokenizer.peekNext().value; if (sn1 == ")" && t1 is TypedContext) { ret = new ParenContext() { parent = context, interior = t1 as TypedContext } } ; else { throw new Exception("yeet"); } } } //blocks and array declaration else if (blockMode == BlockMode.brackets && s0 == "{") { tokenizer.advance(1); var cret = new BlockContext(); while (tokenizer.peekNext().value != "}") { var next = GetContext(context, opDepth, 0, flags); if (next != null) { cret.body.Add(next); } else { throw new Exception("hmm"); } } if (cret.body.Count == 1 && cret.body[0] is SeperatedContext) { tokenizer.advance(0); var aret = new ArrayContext() { parent = context }; aret.content = (cret.body[0] as SeperatedContext)?.children ?? new List <TypedContext>() { cret.body[0] }; aret.type = $"{SysLib.ArrayType.name}<{aret.content[0].type}>"; ret = aret; } else { tokenizer.advance(0); ret = cret; } } //list declaration else if (s0 == "[") { tokenizer.advance(1); var t2 = GetContext(context, opDepth, callDepth + 1, flags); if (tokenizer.peekNext().value != "]") { throw new Exception("Expected one of these: ]"); } var cret = new ListContext(); cret.parent = context; cret.content = (t2 as SeperatedContext)?.children ?? new List <TypedContext>() { t2 }; cret.type = $"{SysLib.ListType.name}<{cret.content[0].type}>"; ret = cret; } //for, while, foreach else if (s0 == "for") { tokenizer.advance(1); var cret = new LoopContext() { parent = context }; var t2 = GetContext(cret, 0, 0, NoBlocks) as ParenContext; if (t2 == null) { throw new Exception("expected a condition for the for loop"); } cret.condition = t2.interior; var t3 = GetContext(cret, 0, 0, 0); cret.body = t3; tokenizer.advance(-1); ret = cret; } else if (s0 == "if") { tokenizer.advance(1); var cret = new IfContext() { parent = context }; var t2 = GetContext(cret, 0, 0, 0) as ParenContext; if (t2 == null || t2.type != SysLib.BoolType.name) { throw new Exception("expected a boolean condition for the if statement"); } cret.condition = t2.interior; var t3 = GetContext(cret, 0, 0, 0); cret.body = t3; // while(tokenizer.peekNext().value == "elif") { // } if (tokenizer.peekNext().value == "else") { tokenizer.advance(1); var eret = new ElseContext() { parent = context, chainParent = cret }; eret.chainParent = cret; var t4 = GetContext(eret, 0, 0, 0); eret.body = t4; ret = eret; } else { ret = cret; } tokenizer.advance(-1); } else if (s0 == "break") { var cret = new BreakContext(); cret.parent = context; cret.type = SysLib.VoidType.name; ret = cret; } //constants else if (int.TryParse(s0, out int i0)) { ret = new ConstContext() { value = i0, type = SysLib.IntType.name } } ; else if (double.TryParse(s0, out double d0)) { ret = new ConstContext() { value = d0, type = SysLib.DoubleType.name } } ; else if (float.TryParse(s0, out float f0)) { ret = new ConstContext() { value = f0, type = SysLib.FloatType.name } } ; else if (long.TryParse(s0, out long l0)) { ret = new ConstContext() { value = l0, type = SysLib.LongType.name } } ; else if (bool.TryParse(s0, out bool b0)) { ret = new ConstContext() { value = b0, type = SysLib.BoolType.name } } ; else if (s0[0] == '"' && s0[s0.Length - 1] == '"') { ret = new ConstContext() { value = s0.Substring(1, s0.Length - 2), type = SysLib.StringType.name } } ; else if (s0.Length == 3 && s0[0] == '\'' && s0[2] == '\'') { ret = new ConstContext() { value = s0[1], type = SysLib.CharType.name } } ; //prefix operators else if (prefixOperators.Contains(s0)) { tokenizer.advance(1); var t2 = GetContext(context, opDepth, callDepth + 1, NoOps); ret = new SimpleOpContext() { a = t2, op = s0 }; tokenizer.advance(-1); } //variables, functions, etc. else { if (ResolveVariable(context, s0, out var match)) { ret = new VarContext() { variable = match } } ; else { if (tokenizer.peekNext().value == ".") { //check imported types //namespace prefixed types string typeName = s0; //reset tokenizer for while loop tokenizer.advance(0); tokenizer.peekNext(); int steps = 0; TypeData td = null; while (!compiler.ValidateType(typeName, out td)) { if (tokenizer.peekNext().value != ".") { break; } typeName += '.' + tokenizer.peekNext().value; steps += 2; } if (td != null) { ret = new StaticTypeContext() { parent = context, type = typeName }; tokenizer.advance(steps); } else { tokenizer.advance(0); } } else { var vc = new VarDecContext() { name = s0 }; context.variables.Add(vc); ret = vc; } } } tokenizer.advance(1); ret.parent = context; //all operators var s1 = tokenizer.peekNext().value; if (flags == NoRecursion) { tokenizer.advance(0); return(ret); } //indexers if ((ret is VarContext || ret is MemberContext) && s1 == "[") { tokenizer.advance(1); var t2 = GetContext(context, 0, callDepth + 1, 0); //get arguments var arguments = t2 is SeperatedContext ? (t2 as SeperatedContext).children : new List <TypedContext>() { t2 }; if (tokenizer.peekNext().value != "]") { throw new Exception("expected one of these: ]"); } if (tokenizer.peekNext().value == "=") { tokenizer.advance(2); var t3 = GetContext(context, 0, callDepth + 1, 0); arguments.Add(t3); var cret = new CallContext() { owner = ret, methodName = "_setIndex", parent = context, arguments = arguments }; if (compiler.ValidateCall(cret, out MethodData md)) { cret.type = md.returnType; ret = cret; } else { throw new Exception("no indexer for this boi"); } } else { var cret = new CallContext() { owner = ret, methodName = "_getIndex", parent = context, arguments = arguments }; if (compiler.ValidateCall(cret, out MethodData md)) { cret.type = md.returnType; ret = cret; } else { throw new Exception("no indexer for this boi"); } tokenizer.advance(1); s1 = tokenizer.peekNext().value; } } //array declaration else if (ret is StaticTypeContext && s1 == "[") { tokenizer.advance(1); if (tokenizer.peekNext().value == "]") { ret = new ListContext() { type = $"{SysLib.ListType.name}<{ret.type}>", parent = context }; } else { var t2 = GetContext(context, 0, callDepth + 1, 0); if (t2.type != SysLib.IntType.name) { throw new Exception("array initializer must have an integer length"); } if (tokenizer.peekNext().value != "]") { throw new Exception("expected one of these: ]"); } ret = new ArrayInitContext() { type = $"{SysLib.ArrayType.name}<{ret.type}>", length = t2, parent = context }; } tokenizer.advance(1); } //calls and member accessing, if (s1 == ".") { while (s1 == ".") { var type = ret.type; var memberOrMethod = tokenizer.peekNext().value; if (tokenizer.peekNext().value == "(") { //method tokenizer.advance(2); var t2 = GetContext(context, 0, callDepth + 1, NoRecursion) as ParenContext; if (t2 == null) { throw new Exception("expected arguments"); } //resolve arguments List <TypedContext> arguments = new List <TypedContext>(); if (t2.interior != null) { if (t2.interior is SeperatedContext) { arguments = ((SeperatedContext)t2.interior).children; } else { arguments.Add(t2); } } var cret = new CallContext() { parent = context, owner = ret, methodName = memberOrMethod, arguments = arguments }; if (compiler.ValidateCall(cret, out MethodData md)) { cret.type = md.returnType; ret = cret; } else { throw new Exception("could not find method"); } tokenizer.advance(0); //if(tokenizer.peekNext().value != ")") throw new Exception("Expected one of these: )"); } else { //member var cret = new MemberContext() { parent = context, owner = ret, memberName = memberOrMethod, }; if (compiler.ValidateMember(cret, out MemberData md)) { tokenizer.advance(2); cret.type = md.returnType; ret = cret; } else { throw new Exception("could not find member"); } } s1 = tokenizer.peekNext().value; } //tokenizer.advance(0); } //Parameter lists else if (s1 == "," && ret is VarDecContext) { var cret = new ParamContext(); var prev = ret as VarDecContext; cret.children.Add(ret); cret.parent = context; while (s1 == ",") { tokenizer.advance(1); var t2 = GetContext(context, 0, callDepth + 1, NoRecursion) as VarDecContext; if (t2 == null) { throw new Exception("excepted parameter"); } if (t2.type == null) { t2.type = prev.type; } prev = t2; cret.children.Add(t2); s1 = tokenizer.peekNext().value; } ret = cret; } //list definition else if (s1 == "," && flags != 4) { var cret = new SeperatedContext(); cret.children.Add(ret); cret.parent = context; while (s1 == ",") { tokenizer.advance(1); var t2 = GetContext(context, 0, callDepth + 1, NoRecursion); cret.children.Add(t2); s1 = tokenizer.peekNext().value; //find common type cret.type = t2.type; } ret = cret; } //assignments if (s1 == "=" && flags != NoOps) { TypedContext variable = ret as VarDecContext ?? (ret as VarContext)?.variable; if (variable == null) { if (ret is MemberContext) { variable = ret; } else { throw new Exception("you can only assign variables"); } } tokenizer.advance(1); var t2 = GetContext(context, opDepth, callDepth + 1, flags); variable.type = t2.type; ret = new AssignContext() { parent = context, variable = ret, value = t2 }; } //from else if (s1 == ":") { var variable = ret as VarDecContext ?? (ret as VarContext).variable; if (variable == null) { throw new Exception("you must get a variable from the following expression"); } tokenizer.advance(1); var t2 = GetContext(context, opDepth, callDepth + 1, flags); var call = new CallContext() { owner = t2, methodName = "_getIter", parent = context }; if (compiler.ValidateCall(call, out MethodData md)) { if (variable.type == null) { variable.type = md.returnType.Between("<", ">"); } } else { throw new Exception("Cannot iterate a type without a _getIter method"); } ret = new FromContext() { parent = context, reference = variable, body = t2 }; } //operators else if (operators.ContainsKey(s1) && flags != NoOps) { tokenizer.advance(1); var t2 = GetContext(context, opDepth + 1, callDepth + 1, flags); var cret = new OpContext() { a = ret, op = s1, b = t2 }; if (t2 is OpContext) { int p0 = operators[s1]; int p1 = operators[((OpContext)t2).op]; if (p0 >= p1) { OpContext deepA = (OpContext)t2; for (; deepA.a is OpContext; deepA = (OpContext)(deepA.a)) { ; } cret.b = deepA.a; deepA.a = cret; cret = (OpContext)t2; } } if (opDepth == 0) { //resolve type ResolveType(cret); } ret = cret; } else { tokenizer.advance(0); } ret.parent = context; return(ret); }
private void ResolveType(TypedContext context) { if (context is ParenContext) { ResolveType((context as ParenContext).interior); } else if (context is SimpleOpContext) { ResolveType((context as SimpleOpContext).a); } else if (context is OpContext) { var opContext = context as OpContext; ResolveType(opContext.a); ResolveType(opContext.b); if (opContext.a.type == opContext.b.type) { opContext.type = opContext.a.type; } else { bool found = false; foreach (var v in implicitConversions) { if (v.Key == opContext.a.type && v.Value == opContext.b.type) { opContext.a = new ConvertContext() { interior = opContext.a, type = v.Value, parent = opContext.parent }; opContext.type = v.Value; found = true; break; } else if (v.Key == opContext.b.type && v.Value == opContext.a.type) { opContext.b = new ConvertContext() { interior = opContext.b, type = v.Value, parent = opContext.parent }; opContext.type = v.Value; found = true; break; } } if (!found) { if (opContext.a.type == SysLib.StringType.name) { opContext.b = new ConvertContext() { interior = opContext.b, type = SysLib.StringType.name, parent = opContext.parent }; opContext.type = SysLib.StringType.name; } else if (opContext.b.type == SysLib.StringType.name) { opContext.a = new ConvertContext() { interior = opContext.a, type = SysLib.StringType.name, parent = opContext.parent }; opContext.type = SysLib.StringType.name; } else { throw new Exception("type not resolved"); } } } if (opContext.op == "==" || opContext.op == "<" || opContext.op == ">" || opContext.op == "!=") { opContext.type = SysLib.BoolType.name; } else if (opContext.op == "->") { opContext.type = $"{SysLib.IterableType.name}<{opContext.type}>"; } } }