/// <summary> /// Process func and changes appropriate S Expressions to cond expressions. /// </summary> /// <param name="func"></param> /// <returns></returns> private static IParsedValue ProcessConds(IParsedValue func) { if (func.ParsedValueType != ParsedValuesTypes.PARSEDSEXPR) return func; if ((func as ParsedSExpr).Members[0].ParsedValueType != ParsedValuesTypes.PARSEDIDENTIFIER) throw new Exception("Something strange happened during cond conversion.\n"); else if (((func as ParsedSExpr).Members[0] as ParsedIdentifier).Name != "cond") { List<IParsedValue> newMembers = new List<IParsedValue>(); foreach (var i in (func as ParsedSExpr).Members) { newMembers.Add(ProcessConds(i)); } (func as ParsedSExpr).Members = newMembers; return func; } else { ParsedCondExpression pce = new ParsedCondExpression(); var mem = (func as ParsedSExpr).Members; for (int i = 1; i < mem.Count; i++) { if (mem[i].ParsedValueType != ParsedValuesTypes.PARSEDSEXPR) throw new Exception("Incorrect cond clause."); var clause = mem[i] as ParsedSExpr; if (clause.Members.Count != 2) throw new Exception("Incorrect cond clause."); pce.Clauses.Add(new CondClause { Condition = ProcessConds(clause.Members[0]), Result = ProcessConds(clause.Members[1]) }); } return pce; } }
/// <summary> /// Rercursive function, valdating function call. /// Raises Exception in case of failure. /// </summary> /// <param name="sexpr">Should contain: FuncName, Params.</param> private void ValidateFuncCall(IParsedValue call) { if (call.ParsedValueType == ParsedValuesTypes.PARSEDSEXPR) { var sexpr = call as ParsedSExpr; Function func = FindFunction(sexpr); List<VarType> callArgList = GetFuncCallArguments(sexpr); List<VarType> funcArgList = func.Arguments.Values.ToList(); if (callArgList.Count != funcArgList.Count) throw new Exception("SA: Wrong arguments list length at " + func.Name + " function call!"); for (int i = 0; i < callArgList.Count; i++) if (!IsTypesCompatible(funcArgList[i], callArgList[i])) throw new Exception("SA: Wrong arguments type at " + func.Name + " function call!"); } else if (call.ParsedValueType == ParsedValuesTypes.PARSEDCOND) { var ccl = call as ParsedCondExpression; foreach (var cl in ccl.Clauses) { ValidateFuncCall(cl.Condition); ValidateFuncCall(cl.Result); } } }
private VarType GetArgumentType(string arg, IParsedValue val) { VarType result = VarType.Any; if (val.ParsedValueType == ParsedValuesTypes.PARSEDSEXPR) { var pse = val as ParsedSExpr; List<IParsedValue> temp = new List<IParsedValue>(pse.Members); // get function Function calledFunc = FindFunction(pse); // remove function name temp.RemoveAt(0); // search in direct parameters foreach (var a in temp.Where(x => x.ParsedValueType == ParsedValuesTypes.PARSEDIDENTIFIER)) { // found our parameter if ((a as ParsedIdentifier).Name == arg) { int idx = temp.IndexOf(a); result = Sup(result, calledFunc.Arguments.ElementAt(idx).Value); } } // search in function calls foreach (var fa in temp.Where(x => x.ParsedValueType == ParsedValuesTypes.PARSEDSEXPR ||x.ParsedValueType == ParsedValuesTypes.PARSEDCOND)) { result = Sup(result, GetArgumentType(arg, fa)); } } else if (val.ParsedValueType == ParsedValuesTypes.PARSEDCOND) { var pse = val as ParsedCondExpression; foreach (var x in pse.Clauses) { result = Sup(result, GetArgumentType(arg, x.Condition)); result = Sup(result, GetArgumentType(arg, x.Result)); } } return result; }
private VarType DeriveIPVRetType(Function context, IParsedValue ipv) { var Result = VarType.Nothing; switch (ipv.ParsedValueType) { case ParsedValuesTypes.PARSEDCHARCONST: return VarType.Char; case ParsedValuesTypes.PARSEDIDENTIFIER: var an = (ipv as ParsedIdentifier).Name; if (an == "nil" || an == "T") return VarType.Any; return context.Arguments[(ipv as ParsedIdentifier).Name]; case ParsedValuesTypes.PARSEDINTEGERCONST: return VarType.Integer; case ParsedValuesTypes.PARSEDSTRINGCONST: return VarType.String; case ParsedValuesTypes.PARSEDCOND: foreach (var s in (ipv as ParsedCondExpression).Clauses) Result = Inf(Result, DeriveIPVRetType(context, s.Result)); return Result; case ParsedValuesTypes.PARSEDSEXPR: var se = ipv as ParsedSExpr; if ((se.Members[0] as ParsedIdentifier).Name == "if") // Crutch return Inf(Result, Inf(DeriveIPVRetType(context, se.Members[1]), DeriveIPVRetType(context, se.Members[1]))); return FindFunction(ipv as ParsedSExpr).RetType; default: // Serious shit. You wont ever see that return VarType.Nothing; } }
/// <summary> /// Generates C code from a IParsedValue. /// </summary> /// <param name="pse"></param> /// <returns>Function C code.</returns> private string GenerateCCode(IParsedValue pse) { string result = ""; switch(pse.ParsedValueType) { case ParsedValuesTypes.PARSEDSEXPR: List<IParsedValue> temp = new List<IParsedValue>((pse as ParsedSExpr).Members); if (temp[0].ParsedValueType != ParsedValuesTypes.PARSEDIDENTIFIER) throw new Exception("CG.GenerateCCode: Not a function call!"); string calledFuncName = (temp[0] as ParsedIdentifier).Name; temp.RemoveAt(0); // standart function call if (FuncDefs[calledFuncName].Body == null) { result += GenerateStandartCFunctionCall(calledFuncName, temp); } else { result += calledFuncName + "( "; bool x = false; foreach (var a in temp) { if (x) result += ", "; x = true; result += GenerateCCode(a); } result += ")"; } break; case ParsedValuesTypes.PARSEDINTEGERCONST: result += (pse as ParsedIntegerConst).Value.ToString(); break; case ParsedValuesTypes.PARSEDIDENTIFIER: result += (pse as ParsedIdentifier).Name; break; case ParsedValuesTypes.PARSEDCHARCONST: result += "'" + (pse as ParsedCharConst).Value + "'"; break; case ParsedValuesTypes.PARSEDSTRINGCONST: result += "\"" + (pse as ParsedStringConst).Value + "\""; break; case ParsedValuesTypes.PARSEDCOND: ParsedCondExpression cond = pse as ParsedCondExpression; result += "{\n"; foreach (var cl in cond.Clauses) { result += "\n\t if ("; if (cl.Condition.ParsedValueType == ParsedValuesTypes.PARSEDCOND) throw new Exception("CG.GenerateCCode: Cond is not accepted as cond condition!"); result += GenerateCCode(cl.Condition) + " )"; if (cl.Result.ParsedValueType == ParsedValuesTypes.PARSEDCOND) result += GenerateCCode(cl.Result); else result += "\n return " + GenerateCCode(cl.Result) + ";\n"; } result += "\n}"; break; default: break; } return result; }