internal static void DefineFunction(CType signature, string name, CStorageClass cStorageClass) { //cStorageClass (static, extern, or none) //ignore for now if (currentFunctionScope != null || BlockScopes.Count > 0) { throw new SemanticException("can only define function at file scope"); } else { if (fileScope.ContainsKey(name)) { if (fileScope[name].functionBody == null && fileScope[name].type.Equals(signature)) { fileScope[name].functionBody = CStatment.PopStatement(); } else { throw new SemanticException("canot redifein function"); } } else { fileScope[name] = new CIdentifier(signature, name, CStatment.PopStatement()); } } }
public static void EndCompoundStatement(List <CCompoundStatmentItemType> itemTypes) { CIdentifier.ExitBlockScope(); List <CStatment> blockBody = new List <CStatment>(); List <int> localVarSizes = new List <int>(); //the item types come in sequential order (top to bottom), but they are sitting on the stack in reverse order (botom to top) //revers the list to deal with this itemTypes.Reverse(); foreach (var itemType in itemTypes) { if (itemType == CCompoundStatmentItemType.Statment) { CStatment stat = PopStatement(); blockBody.Add(stat); } else { CDeclaration decl = CDeclaration.PopDecl(); localVarSizes.Add(decl.Size); //get a statments that initilizes the local variable (or does nothing if it is not a definition) blockBody.Add(decl.GetDefinitionStatment()); } } //put the statments back in top to bottom order blockBody.Reverse(); PushStatement(new CStatment(blockBody, localVarSizes)); }
public override void ExitIterationStatement(CParser.IterationStatementContext context) { //'while' '(' expression ')' statement if (context.GetText().StartsWith("while")) { SafeCall(context, CStatment.EndWhileLoopStatement); } //'do' statement 'while' '(' expression ')' ';' else if (context.GetText().StartsWith("do")) { SafeCall(context, CStatment.EndDoWhileLoopStatement); } else { //'for' '(' declaration expression? ';' expression? ')' statement if (context.declaration() != null) { SafeCall(context, () => CStatment.EndForLoopStatement(CForInitType.Decl, context.expression(0) != null, context.expression(1) != null)); } //'for' '(' expression? ';' expression? ';' expression? ')' statement else { SafeCall(context, () => CStatment.EndForLoopStatement(context.expression(0) != null ? CForInitType.Expression : CForInitType.None, context.expression(1) != null, context.expression(2) != null)); } } }
private static void CleanBlock(Dictionary <string, CIdentifier> dictionary) { foreach (CIdentifier ident in dictionary.Values) { CStatment.PopLocal(ident.type.Size); } }
public override void ExitJumpStatement(CParser.JumpStatementContext context) { //'goto' Identifier ';' if (context.Identifier() != null) { SafeCall(context, () => CStatment.GotoStatement(context.Identifier().GetText())); } //'continue' ';' else if (context.GetText().StartsWith("continue")) { SafeCall(context, CStatment.ContinueStatement); } //'break' ';' else if (context.GetText().StartsWith("break")) { SafeCall(context, CStatment.BreakStatement); } //'return' expression? ';' else if (context.GetText().StartsWith("return")) { SafeCall(context, () => CStatment.ReturnStatement(context.expression() != null)); } //'goto' unaryExpression ';' -- GCC extension not supported else { SematicError(context, "gcc goto extention not supported"); } }
//todo handle scope public static CIdentifier CreateIdentifierInCurrentScope(string name, CType cType, CStorageClass StorageClass = CStorageClass.Ignore, CConstType ConstType = CConstType.Ignore) { if (CType.InStructDefinition) { //member variable CIdentifier ident = new CIdentifier(cType, name, true, false, 0, CType.MemberOffset(cType.Size)); CType.GlobalStructMembers.Add(ident); return(ident); } else if (BlockScopes.Count > 0) { if (BlockScopes[BlockScopes.Count - 1].ContainsKey(name)) { throw new SemanticException("idenitier " + name + " is already defined in this scope"); } //local var CIdentifier ident = new CIdentifier(cType, name, false, true, CStatment.PushLocal(cType.Size), 0); BlockScopes[BlockScopes.Count - 1][name] = ident; return(ident); } else { if (fileScope.ContainsKey(name)) { throw new SemanticException("idenitier " + name + " is already defined in this scope"); } //global var CIdentifier ident = new CIdentifier(cType, name, false, false, 0, 0); fileScope[name] = ident; return(ident); } }
public CStatment GetDefinitionStatment() { CStatment.BeginCompoundStatement(); int stats = 0; foreach (CIdentifier ident in idents) { if (ident.Init != null) { CStatment.PushStatement(ident.GetDefinitionStatment()); stats++; } } List <CCompoundStatmentItemType> items = new List <CCompoundStatmentItemType>(); for (int i = 0; i < stats; i++) { items.Add(CCompoundStatmentItemType.Statment); } CStatment.EndCompoundStatement(items); return(CStatment.PopStatement()); }
//function public CIdentifier(CType signature, string name, CStatment cStatment) { //TODO check return type of function //TODO (big job) check for "not all paths return a value" this.name = name; this.type = signature; this.functionBody = cStatment; }
//STATEMENTS //http://en.cppreference.com/w/c/language/statements public override void ExitStatement(CParser.StatementContext context) { if (context.StringLiteral() != null) { //'asm' '(' StringLiteral ')'';' CStatment.AsmStatement(context.StringLiteral().GetText()); } }
public static void EndWhileLoopStatement() { CExpression expr = CExpression.PopExpression(); CStatment stat = PopStatement(); //loopCheck: if(expression) goto loopBody; if (!expr.IsScalar) { throw new SemanticException("condition expression in loop must be scalar"); } CStatment gotoBody = new CStatment(loopBodyLabels.Peek()); CExpression.PushExpression(expr); PushStatement(gotoBody); IfStatement(false); CStatment ifCheckGotoBody = PopStatement(); ifCheckGotoBody.AddLabel(loopChechLabels.Peek().Name); //goto endloop: CStatment gotoEnd = new CStatment(endLoopLabels.Peek()); //loopBody: statment; CStatment loopBody = stat; loopBody.AddLabel(loopBodyLabels.Peek().Name); //goto loopCheck; CStatment gotoCheck = new CStatment(loopChechLabels.Peek()); //endLoop: {}; CStatment end = new CStatment(); end.AddLabel(endLoopLabels.Peek().Name); PushStatement(ifCheckGotoBody); PushStatement(gotoEnd); PushStatement(loopBody); PushStatement(gotoCheck); PushStatement(end); ExitLoop(); EndCompoundStatement(new List <CCompoundStatmentItemType> { CCompoundStatmentItemType.Statment, CCompoundStatmentItemType.Statment, CCompoundStatmentItemType.Statment, CCompoundStatmentItemType.Statment, CCompoundStatmentItemType.Statment } ); PushStatement(PopStatement()); }
public override void ExitSelectionStatement(CParser.SelectionStatementContext context) { //'if' '(' expression ')' statement ('else' statement)? if (context.GetText().StartsWith("if")) { SafeCall(context, () => CStatment.IfStatement(context.statement(1) != null)); } //'switch' '(' expression ')' statement else { SafeCall(context, CStatment.EndSwitchStatement); } }
//if statment public CStatment(CExpression cExpression, CStatment cStatment) { string ifBody = CIdentifier.AutoGenerateLabel("ifBody"); string EndIf = CIdentifier.AutoGenerateLabel("endIf"); Add(cExpression); Add(new OpCodeEmitter(OpCode.PUSHW, ifBody)); Add(new OpCodeEmitter(OpCode.JIF)); Add(new OpCodeEmitter(OpCode.PUSHW, EndIf)); Add(new OpCodeEmitter(OpCode.JMP)); Add(new LabelEmitter(ifBody)); Add(cStatment); Add(new LabelEmitter(EndIf)); }
internal static void AsmStatement(string asm) { string[] parts = asm.Trim('"').Split(); OpCode code = (OpCode)Enum.Parse(typeof(OpCode), parts[0]); string arg = parts.Length > 1 ? parts[1] : ""; OpCodeEmitter asmOp = new OpCodeEmitter(code, arg); CStatment stat = new CStatment(); stat.Add(asmOp); PushStatement(stat); }
public override void ExitLabeledStatement(CParser.LabeledStatementContext context) { //Identifier ':' statement if (context.Identifier() != null) { SafeCall(context, () => CStatment.LabeledStatement(context.Identifier().GetText())); } //'case' constantExpression ':' statement else if (context.constantExpression() != null) { SafeCall(context, CStatment.CaseStatement); } //'default' ':' statement else { SafeCall(context, CStatment.DefaultStatement); } }
public override void EnterIterationStatement(CParser.IterationStatementContext context) { //beginwhile //begindowhile //begin for if (context.GetText().StartsWith("while")) { CStatment.BeginWhileLoopStatement(); } //'do' statement 'while' '(' expression ')' ';' else if (context.GetText().StartsWith("do")) { CStatment.BeginDoWhileLoopStatement(); } else { CStatment.BeginForLoopStatement(); } }
//http://en.cppreference.com/w/c/language/if public static void IfStatement(bool hasElse) { //expression must be an expression of any scalar type. //If expression compares not equal to the integer zero, statement_true is executed. //In the else form, if expression compares equal to the integer zero, statement_false is executed. //if ( expression ) statement_true if (!hasElse) { PushStatement(new CStatment(CExpression.PopExpression(), PopStatement())); } //if ( expression ) statement_true else statement_false else { CStatment els = PopStatement(); CStatment fi = PopStatement(); PushStatement(new CStatment(CExpression.PopExpression(), fi, els)); } }
internal CStatment GetDefinitionStatment() { if (Init == null) { return(new CStatment()); } if (type.IsStruct) { throw new SemanticException("local variables of type struct are not implimentd"); } else if (type.IsArray || Init.IsList) { throw new SemanticException("local variables of type array are not implimentd"); } else if (type.TypeClass == CTypeClass.CFunction) { throw new InvalidOperationException("wtf how did you declare a local function varable"); } else if (type.TypeClass == CTypeClass.CVoid) { throw new InvalidOperationException("wtf how did you declare a local void varable"); } else { OpCode PushOp; if (type.Size == 1) { PushOp = OpCode.PUSHB; } else if (type.Size == 2) { PushOp = OpCode.PUSHH; } else if (type.Size == 4) { PushOp = OpCode.PUSHW; } else { throw new InvalidOperationException("local variable of unknown size"); } CStatment initilize = new CStatment(); initilize.Add(new OpCodeEmitter(PushOp, "0")); CExpression localAddr = new CExpression(type, ValueCatagory.LValue); localAddr.Add(new OpCodeEmitter(OpCode.PUSHBP)); localAddr.Add(new OpCodeEmitter(OpCode.PUSHW, stackPointerOffset.ToString())); localAddr.Add(new OpCodeEmitter(OpCode.ADD)); CExpression.PushExpression(localAddr); CExpression.PushExpression(Init.Expression); CExpression.BasicAssignmentOperator(); initilize.Add(new CStatment(CExpression.PopExpression())); return(initilize); } }
public static void EndForLoopStatement(CForInitType initType, bool hasConditionExpression, bool hasIterationExpression) { List <CCompoundStatmentItemType> compondItems = new List <CCompoundStatmentItemType> { CCompoundStatmentItemType.Statment, CCompoundStatmentItemType.Statment }; CStatment loopBody = PopStatement(); CStatment iterationStatement = hasIterationExpression ? new CStatment(CExpression.PopExpression()) : new CStatment(); CExpression condition; if (hasConditionExpression) { condition = CExpression.PopExpression(); } else { CExpression.PushConstant("1"); condition = CExpression.PopExpression(); } //init_claus CStatment initClaus; if (initType == CForInitType.Decl) { initClaus = CDeclaration.PopDecl().GetDefinitionStatment(); } else if (initType == CForInitType.Expression) { initClaus = new CStatment(CExpression.PopExpression()); } else { initClaus = new CStatment(); } // contruct loop body BeginCompoundStatement(); PushStatement(loopBody); PushStatement(iterationStatement); EndCompoundStatement(compondItems); CStatment loopbody = PopStatement(); // while(cond_expression) loopbody CExpression.PushExpression(condition); PushStatement(loopBody); BeginWhileLoopStatement(); EndWhileLoopStatement(); CStatment whilestat = PopStatement(); PushStatement(initClaus); PushStatement(whilestat); EndCompoundStatement(compondItems); PushStatement(PopStatement()); }
public static void PushStatement(CStatment statment) { statments.Push(statment); }
public override void ExitCompoundStatement(CParser.CompoundStatementContext context) { //'{' blockItemList? '}' SafeCall(context, () => CStatment.EndCompoundStatement(GetBlockItemTypes(context.blockItemList()))); }