public override void GenerateCode(Emit.ILGenerator ilg, ExecutionContext ec) { /* * Check for two things: * 1) Is it an argument? * 2) Is it a local variable (or global) */ var arg = ec.GetParameter(varName); if (arg != null) { //This is an argument - we need to store it in its index. ilg.Emit(Emit.OpCodes.Starg, arg.Position); return; } var varDec = ec.GetVariable(varName); if (varDec == null) { //The person wants this to be a local variable. It has not been declared, so we must do it for them. varDec = ilg.DeclareLocal(e.GetEvaluatedType(ec)); ec.AddVariable(varName, varDec); } e.Push(ilg, ec); ilg.Emit(Emit.OpCodes.Stloc, varDec); //Store the result of the expression. }
public override void Push(Emit.ILGenerator ilg, ExecutionContext ec) { var f = Function.Get(funcName).MethodInfo; var fec = Function.Get(funcName).Ec; int count = 0; var pars = fec.GetParameters(); foreach (Expression e in alist) { if (count >= fec.NumParameters) throw new Exception("Too many arguments to function."); if (pars[count++].Type == e.GetEvaluatedType(ec)) { e.Push(ilg, ec); } else { throw new Exception("Mismatch of argument types - no coercing available currently."); } } if (count < fec.NumParameters) throw new Exception("Too few arguments to function."); ilg.Emit(Emit.OpCodes.Call, Function.Get(funcName).MethodInfo); }
//For use with already-defined functions, like Console.WriteLine. Allows you to alias them for use inside the language. public Function(String funcName, MethodInfo mi) { fns.Add(funcName, this); this.mi = mi; ec = new ExecutionContext(null); var parInfos = mi.GetParameters(); Parameter[] pars = new Parameter[parInfos.Length]; for (int i = 0; i < pars.Length; i++) pars[i] = new Parameter(parInfos[i].ParameterType, parInfos[i].Name); ec.SetParameters(pars); }
public Function(Identifier returnType, Identifier name, Sequence<Parameter> pars, Sequence<Statement> stmts) { Type[] tar = Parameter.ConvertSequenceToTypeArray(pars); var mb = CodeGenerator.CreateFunction(name.Value, TypeChecker.ConvertStringToType(returnType.Value), tar); mi = mb; this.stmts = stmts; if (fns.ContainsKey(name.Value)) { throw new Exception("Function redeclared. Note: overloaded functions are not supported at this time."); } fns.Add(name.Value, this); int count = 1; //parameters start at index 1 - 0 is the return. not sure on GetParameters() though - more testing is needed, but i don't think it includes the returntype as there is a separate way to get that foreach (Parameter p in pars) { mb.DefineParameter(count++, ParameterAttributes.None, p.Name); } ec = new ExecutionContext(null); ec.SetParameters(pars.ToArray()); }
public override Type GetEvaluatedType(ExecutionContext ec) { return typeof(string); }
public abstract void Push(Emit.ILGenerator ilg, ExecutionContext ec);
public abstract void GenerateCode(Emit.ILGenerator ilg, ExecutionContext ec);
public abstract Type GetEvaluatedType(Expression left, Expression right, ExecutionContext ec);
public override Type GetEvaluatedType(Expression left, Expression right, ExecutionContext ec) { throw new NotImplementedException("Non + operators are not implemented."); }
public override Type GetEvaluatedType(Expression left, Expression right, ExecutionContext ec) { Type t = left.GetEvaluatedType(ec); Type t2 = right.GetEvaluatedType(ec); if (t != t2) { throw new NotImplementedException("Type coercion not implemented yet."); } return t; //same type because you're adding! }
public override void Push(Emit.ILGenerator ilg, ExecutionContext ec) { /* * Check for three things: * 1) Is it an argument? * 2) Is it a local variable (or global) * 3) Is it a function call without parantheses? */ var arg = ec.GetParameter(name); if (arg != null) { //This is an argument - push its index onto the stack! ilg.Emit(Emit.OpCodes.Ldarg, arg.Position); return; } var varDec = ec.GetVariable(name); if (varDec != null) { //This is a local variable! Push it onto the stack. ilg.Emit(Emit.OpCodes.Ldloc, varDec); return; } var funcDec = Function.Get(name); if (funcDec != null) { if (funcDec.MethodInfo.ReturnType != typeof(void)) { ilg.Emit(Emit.OpCodes.Call, funcDec.MethodInfo); //Only functions without parameters can be called currently - changes to the grammar are needed to improve on this and will likely become their own type of expression return; } else { throw new Exception("Attempting to use a void type as an expression."); } } //At this point, we have an unrecognized identifier throw new Exception("Use of undeclared identifier in expression."); }
public override Type GetEvaluatedType(ExecutionContext ec) { var arg = ec.GetParameter(name); if (arg != null) { return arg.Type; } var varDec = ec.GetVariable(name); if (varDec != null) { return varDec.LocalType; } var funcDec = Function.Get(name); if (funcDec != null) { return funcDec.MethodInfo.ReturnType; } //At this point, we have an unrecognized identifier throw new Exception("Use of undeclared identifier in expression."); }
public override void GenerateCode(Emit.ILGenerator ilg, ExecutionContext ec) { this.fc.Push(ilg, ec); }
public override void Push(Emit.ILGenerator ilg, ExecutionContext ec) { ilg.Emit(Emit.OpCodes.Ldstr, s); }
public override Type GetEvaluatedType(ExecutionContext ec) { return this.o.GetEvaluatedType(left, right, ec); }
public override Type GetEvaluatedType(ExecutionContext ec) { return Function.Get(funcName).MethodInfo.ReturnType; }
public override void Push(Emit.ILGenerator ilg, ExecutionContext ec) { this.o.Evaluate(left, right, ilg, ec); }
public ExecutionContext(ExecutionContext p) { this.parent = p; }
public override Type GetEvaluatedType(ExecutionContext ec) { throw new NotImplementedException(); }
public override void Evaluate(Expression left, Expression right, Emit.ILGenerator ilg, ExecutionContext ec) { throw new NotImplementedException("Non + operators are not implemented."); }
public override void Push(Emit.ILGenerator ilg, ExecutionContext ec) { throw new NotImplementedException(); }
public abstract void Evaluate(Expression left, Expression right, Emit.ILGenerator ilg, ExecutionContext ec);
public abstract Type GetEvaluatedType(ExecutionContext ec);
public override void Evaluate(Expression left, Expression right, Emit.ILGenerator ilg, ExecutionContext ec) { Type t = left.GetEvaluatedType(ec); Type t2 = right.GetEvaluatedType(ec); if (t != t2) { throw new NotImplementedException("Type coercion not implemented yet."); } if (t == typeof(string)) { //Concatenate strings! Fun for all. //TODO: optimize the shit out of this to determine if there is tons of concatenating going on because this is inefficient as hell for something like "lol" + "hi" + 3 //TODO: classes with operator overloading so I don't need to do special exceptions within the language code itself. I dislike that. left.Push(ilg, ec); right.Push(ilg, ec); ilg.Emit(Emit.OpCodes.Call, typeof(String).GetMethod("Concat", new Type[] { typeof(string), typeof(string) })); } }
public override void GenerateCode(Emit.ILGenerator ilg, ExecutionContext ec) { if (this.returnExp != null) this.returnExp.Push(ilg, ec); ilg.Emit(Emit.OpCodes.Ret); }