public void GenClassItems(WalkState ws, ITypeContainer parent) { var c = parent.GetClass(ws.Assembly, ws.Namespace, Name, Public); foreach (var s in Statements) { var t = s.GetType(); if (t == typeof(Class)) { (s as Class).GenClassItems(ws, c); } else if (t == typeof(FunctionDef)) { c.Functions.Add(new Function(c, s as FunctionDef, ws)); } else if (t == typeof(PropertySet)) { var ps = s as PropertySet; if (ps.CalcTypeList(ws)) { ExprList el = null; if (ps.Vals != null) { el = ps.Vals as ExprList; if (ps.Props.Count != el.Expressions.Count) { ws.AddError("Mismatched property/value counts: " + ps.Props.Count + " != " + el.Expressions.Count); el = null; } } for (int i = 0; i < ps.Props.Count; i++) { var p = ps.Props[i]; var prop = p.Static ? new Constant(p, ws) : new Field(p, ws); prop.CreateField(c); if (el != null) { object val = el.Expressions[i].Calculate(ws); if (val != null) { prop.SetDefault(p.SystemType.Cast(val, ws)); } // TODO - Do something with default values for fields. } c.Fields.Add(prop); } } } else { ws.AddError("Unknown class statement: " + t); } } }
public static bool CalcTypeList(this List<Variable> ps, WalkState ws) { Type type = null; for (int i = ps.Count - 1; i >= 0; i--) { if (ps[i].Type == null) { ps[i].SystemType = type; } else { type = ps[i].Type.ToType(ws); ps[i].SystemType = type; } } bool retVal = true; foreach (var p in ps) { if (p.SystemType == null) { ws.AddError("Type could not be determined for " + p.Name); retVal = false; } } return retVal; }
public List<Type> CalcTypes(WalkState ws) { List<Type> ltl = Left.CalcTypes(ws); List<Type> rtl = Right.CalcTypes(ws); if (ltl.Count == rtl.Count && ltl.Count == 1) { Type lt = ltl[0]; Type rt = rtl[0]; if (Op.IsBooleanOp()) { return new List<Type> { typeof(bool) }; } else if (Op == TokenType.As) { return rtl; } else if (lt == typeof(string) || rt == typeof(string)) { return new List<Type> { typeof(string) }; } else if (lt == rt) { return ltl; } } ws.AddError("Cannot apply binary operator " + Op + " with " + ltl.Count + " type(s) and " + rtl.Count + " type(s)."); return new List<Type> { }; }
public void GenTypes(WalkState ws, ITypeContainer parent) { if (!string.IsNullOrEmpty(ws.Namespace)) { var c = parent.GetClass(ws.Assembly, ws.Namespace, Name, Public); foreach(var s in Statements) { var t = s.GetType(); if (t == typeof(Class)) { (s as Class).GenTypes(ws, c); } } } else { ws.AddError("No namespace specified for class " + Name); } }
public static bool CalcTypeList(this PropertySet ps, WalkState ws) { Type type = null; for (int i = ps.Props.Count - 1; i >= 0; i--) { if (ps.Props[i].Type == null) { ps.Props[i].SystemType = type; } else { type = ps.Props[i].Type.ToType(ws); ps.Props[i].SystemType = type; } } if (ps.Vals != null) { var types = (ps.Vals as ExprList).CalcTypes(ws); if (ps.Props.Count == types.Count) { for (int i = 0; i < ps.Props.Count; i++) { if (ps.Props[i].SystemType == null) { ps.Props[i].SystemType = types[i]; } } } } bool retVal = true; foreach (var p in ps.Props) { if (p.SystemType == null) { ws.AddError("Type could not be determined for " + p.Name); retVal = false; } } return retVal; }
public object Calculate(WalkState ws) { Type lt, rt; object left = Left.Calculate(ws); object right = Right.Calculate(ws); switch (Op) { case TokenType.As: rt = Right.CalcTypes(ws)[0]; return rt.Cast(left, ws); case TokenType.Is: var lts = Left.CalcTypes(ws); rt = Right.CalcTypes(ws)[0]; return (lts.Count == 1 && lts[0] == rt); case TokenType.Add: lt = CalcTypes(ws)[0]; if (lt.IsFloatingPointType()) { return lt.Cast(Convert.ToDouble(left) + Convert.ToDouble(right), ws); } else if (lt.IsIntegerType()) { return lt.Cast(Convert.ToInt64(left) + Convert.ToInt64(right), ws); } else if (lt == typeof(string)) { return left.ToString() + right.ToString(); } break; case TokenType.Sub: lt = CalcTypes(ws)[0]; if (lt.IsFloatingPointType()) { return lt.Cast(Convert.ToDouble(left) - Convert.ToDouble(right), ws); } else if (lt.IsIntegerType()) { return lt.Cast(Convert.ToInt64(left) - Convert.ToInt64(right), ws); } break; case TokenType.Mul: lt = CalcTypes(ws)[0]; if (lt.IsFloatingPointType()) { return lt.Cast(Convert.ToDouble(left) * Convert.ToDouble(right), ws); } else if (lt.IsIntegerType()) { return lt.Cast(Convert.ToInt64(left) * Convert.ToInt64(right), ws); } break; case TokenType.Div: lt = CalcTypes(ws)[0]; if (lt.IsFloatingPointType()) { return lt.Cast(Convert.ToDouble(left) / Convert.ToDouble(right), ws); } else if (lt.IsIntegerType()) { return lt.Cast(Convert.ToInt64(left) / Convert.ToInt64(right), ws); } break; case TokenType.Mod: lt = CalcTypes(ws)[0]; if (lt.IsIntegerType()) { return lt.Cast(Convert.ToInt64(left) % Convert.ToInt64(right), ws); } break; case TokenType.BAnd: case TokenType.BOr: case TokenType.BXOr: break; case TokenType.Equal: return (left as IComparable).CompareTo(right) == 0; case TokenType.NotEqual: return (left as IComparable).CompareTo(right) != 0; case TokenType.LeftCaret: return (left as IComparable).CompareTo(right) < 0; case TokenType.LtEqual: return (left as IComparable).CompareTo(right) < 1; case TokenType.RightCaret: return (left as IComparable).CompareTo(right) > 0; case TokenType.GtEqual: return (left as IComparable).CompareTo(right) > -1; case TokenType.And: return ((bool)left) && ((bool)right); case TokenType.Or: return ((bool)left) || ((bool)right); } ws.AddError("Could not calculate binary operator: " + Op); return null; }
public object Calculate(WalkState ws) { var ts = Expr.CalcTypes(ws); if (ts.Count != 1) { ws.AddError("Cannot use a unary operator on a type with " + ts.Count + " return type(s)."); return null; } Type type = ts[0]; var val = Expr.Calculate(ws); switch (Op) { case TokenType.Sub: if (type.IsFloatingPointType()) { return type.Cast(-Convert.ToDouble(val), ws); } else if (type.IsIntegerType()) { return type.Cast(-Convert.ToInt64(val), ws); } ws.AddError("Cannot negate a field of type " + type); return null; case TokenType.Not: if (type == typeof(bool)) { return !(bool)val; } ws.AddError("Cannot use not on a field of type " + type); return null; } ws.AddError("Unknown unary op encountered when calculating value: " + Op); return null; }
public static object Cast(this Type type, object val, WalkState ws) { if (type == typeof(bool)) { return Convert.ToBoolean(val); } else if (type == typeof(char)) { return Convert.ToChar(val); } else if (type == typeof(float)) { return Convert.ToSingle(val); } else if (type == typeof(double)) { return Convert.ToDouble(val); } else if (type == typeof(sbyte)) { return Convert.ToSByte(val); } else if (type == typeof(short)) { return Convert.ToInt16(val); } else if (type == typeof(int)) { return Convert.ToInt32(val); } else if (type == typeof(long)) { return Convert.ToInt64(val); } else if (type == typeof(byte)) { return Convert.ToByte(val); } else if (type == typeof(ushort)) { return Convert.ToUInt16(val); } else if (type == typeof(uint)) { return Convert.ToUInt32(val); } else if (type == typeof(ulong)) { return Convert.ToUInt64(val); } else if (type == typeof(string)) { return Convert.ToString(val); } ws.AddError("Cannot convert '" + val + "' to " + type); return null; }
public static Type ToType(this IStatement type, WalkState ws) { var t = type.GetType(); if (t == typeof(Array)) { var ar = type as Array; var at = ar.Type.ToType(ws); if (ar.Dimensions == 1) { return at.MakeArrayType(); } return at.MakeArrayType(ar.Dimensions); } else if (t == typeof(Identifier)) { var id = type as Identifier; switch (id.ToString()) { case "any": return typeof(object); case "bool": return typeof(bool); case "char": return typeof(char); case "f32": return typeof(float); case "f64": return typeof(double); case "i8": return typeof(sbyte); case "i16": return typeof(short); case "i32": return typeof(int); case "i64": return typeof(long); case "string": return typeof(string); case "u8": return typeof(byte); case "u16": return typeof(ushort); case "u32": return typeof(uint); case "u64": return typeof(ulong); default: ws.AddError("Unknown type string '" + id.ToString() + "'"); return null; } } ws.AddError("Unknown type '" + t + "' encountered."); return null; }
public void GenFunctionBody(WalkState ws) { var il = MethodBuilder.GetILGenerator(); foreach (var s in Statements) { var t = s.GetType(); if (t == typeof(ExprStmt)) { var es = s as ExprStmt; var el = es.Expr as ExprList; if (el.Expressions.Count > 1) { ws.AddError("Cannot have more than a single expression as a statement."); } else { var et = el.Expressions[0].GetType(); if (et == typeof(FunctionCall)) { var fn = el.Expressions[0] as FunctionCall; // TODO - Function call } else { ws.AddError(et + " is not valid for a statement."); } } } else if (t == typeof(Return)) { var r = s as Return; if (r.Vals != null) { var el = r.Vals as ExprList; for (int i = 1; i < el.Expressions.Count; i++) { // TODO - multiple return values } el.Expressions[0].Emit(il, ws); } il.Emit(OpCodes.Ret); } else { ws.AddError("Invalid method instruction " + t); } } // If no commands have been emitted, emit a single return. if (il.ILOffset == 0) { il.Emit(OpCodes.Ret); } }