public AssemblyBuilder(bool verbose = true) { ExecBlocks = new List <BaseExecBlockContext>(); Symbols = new List <DatSymbol>(); _symbolsDict = new Dictionary <string, DatSymbol>(); _activeContext = null; ActiveExecBlock = null; _assignmentLeftSide = new List <SymbolInstruction>(); FuncCallCtx = null; _nextStringSymbolNumber = 10000; IsInsideConstDef = false; IsCurrentlyParsingExternals = false; IsInsideArgList = false; IsInsideAssignment = false; IsInsideReturnStatement = false; AssignmentType = DatSymbolType.Undefined; _nextSymbolIndex = 0; _verbose = verbose; Errors = new List <CompilationMessage>(); ErrorContext = new ErrorContext(this); }
public AssemblyElement GetProperPushInstruction(DatSymbol symbol, int arrIndex) { BaseExecBlockContext activeBlock = ActiveExecBlock; if (arrIndex > 0) { return(new PushArrayVar(symbol, arrIndex)); } if (IsInsideArgList) { return(PushSymbol(symbol, FuncCallCtx.GetParameterType())); } if (IsInsideReturnStatement && activeBlock != null) { return(PushSymbol(symbol, activeBlock.GetSymbol().ReturnType)); } if (IsInsideAssignment) { return(PushSymbol(symbol, AssignmentType)); } if (IsInsideIfCondition) { return(PushSymbol(symbol, DatSymbolType.Int)); } return(PushSymbol(symbol)); }
public override void ExitParameterList(DaedalusParser.ParameterListContext context) { var parameterDeclContexts = context.parameterDecl(); foreach (var parameterDeclContext in parameterDeclContexts.Reverse()) { BaseExecBlockContext baseExecBlock = _assemblyBuilder.ExecBlocks.Last(); string execBlockName = baseExecBlock.GetSymbol().Name; string parameterLocalName = parameterDeclContext.nameNode().GetText(); string parameterName = $"{execBlockName}.{parameterLocalName}"; DatSymbol parameterSymbol = _assemblyBuilder.ResolveSymbol(parameterName); var assignInstruction = AssemblyBuilderHelpers.GetAssignInstructionForDatSymbolType(parameterSymbol.Type); if (parameterSymbol.Type is DatSymbolType.Instance) { _assemblyBuilder.AddInstruction(new PushInstance(parameterSymbol)); } else { _assemblyBuilder.AddInstruction(new PushVar(parameterSymbol)); } _assemblyBuilder.AddInstruction(assignInstruction); } }
public override void EnterVarDecl([NotNull] DaedalusParser.VarDeclContext context) { if (context.Parent.Parent is DaedalusParser.DaedalusFileContext || _assemblyBuilder.IsContextInsideExecBlock()) { var typeName = context.typeReference().GetText(); var type = DatSymbolTypeFromString(typeName); if (type == DatSymbolType.Class) { type = DatSymbolType.Instance; } for (int i = 0; i < context.ChildCount; i++) { var varContext = context.GetChild(i); if (varContext is TerminalNodeImpl) { continue; // skips ',' } if (varContext is DaedalusParser.VarValueDeclContext varValueContext) { var name = varValueContext.nameNode().GetText(); if (_assemblyBuilder.IsContextInsideExecBlock()) { // TODO consider making assemblyBuilder.active public and using it here BaseExecBlockContext baseExecBlock = _assemblyBuilder.ExecBlocks.Last(); string execBlockName = baseExecBlock.GetSymbol().Name; name = $"{execBlockName}.{name}"; } var location = GetLocation(context); int parentIndex = DatSymbol.NULL_INDEX; string parameterTypeName = context.typeReference().GetText(); DatSymbolType?parameterType = DatSymbolTypeFromString(parameterTypeName); if (parameterType is DatSymbolType.Class) { var parentSymbol = _assemblyBuilder.ResolveSymbol(parameterTypeName); parentIndex = parentSymbol.Index; } var symbol = SymbolBuilder.BuildVariable(name, type, location, parentIndex); // TODO : Validate params _assemblyBuilder.AddSymbol(symbol); } if (varContext is DaedalusParser.VarArrayDeclContext varArrayContext) { var name = varArrayContext.nameNode().GetText(); var location = GetLocation(context); var size = EvaluatorHelper.EvaluteArraySize(varArrayContext.arraySize(), _assemblyBuilder); var symbol = SymbolBuilder.BuildArrOfVariables(name, type, (uint)size, location); // TODO : Validate params _assemblyBuilder.AddSymbol(symbol); } } } }
public AssemblyBuilderSnapshot(AssemblyBuilder assemblyBuilder) { ActiveExecBlock = assemblyBuilder.ActiveExecBlock; IsInsideArgList = assemblyBuilder.IsInsideArgList; IsInsideAssignment = assemblyBuilder.IsInsideAssignment; IsInsideIfCondition = assemblyBuilder.IsInsideIfCondition; IsInsideReturnStatement = assemblyBuilder.IsInsideReturnStatement; AssignmentType = assemblyBuilder.AssignmentType; FuncCallCtx = assemblyBuilder.FuncCallCtx == null ? null : new FuncCallContext(assemblyBuilder.FuncCallCtx); }
public void LoadStateFromSnapshot(AssemblyBuilderSnapshot snapshot) { ActiveExecBlock = snapshot.ActiveExecBlock; IsInsideArgList = snapshot.IsInsideArgList; IsInsideAssignment = snapshot.IsInsideAssignment; IsInsideIfCondition = snapshot.IsInsideIfCondition; IsInsideReturnStatement = snapshot.IsInsideReturnStatement; AssignmentType = snapshot.AssignmentType; FuncCallCtx = snapshot.FuncCallCtx; }
public override void EnterParameterDecl(DaedalusParser.ParameterDeclContext context) { BaseExecBlockContext baseExecBlock = _assemblyBuilder.ExecBlocks.Last(); string execBlockName = baseExecBlock.GetSymbol().Name; string parameterLocalName = context.nameNode().GetText(); string parameterName = $"{execBlockName}.{parameterLocalName}"; int parentIndex = DatSymbol.NULL_INDEX; string parameterTypeName = context.typeReference().GetText(); DatSymbolType?parameterType = DatSymbolTypeFromString(parameterTypeName); if (parameterType is DatSymbolType.Class) { parameterType = DatSymbolType.Instance; var parentSymbol = _assemblyBuilder.ResolveSymbol(parameterTypeName); parentIndex = parentSymbol.Index; } DatSymbol symbol; var location = GetLocation(context); var arraySizeContext = context.arraySize(); if (arraySizeContext != null) { if (!uint.TryParse(arraySizeContext.GetText(), out var arrIndex)) { var constSymbol = _assemblyBuilder.ResolveSymbol(arraySizeContext.GetText()); if (constSymbol.Flags != DatSymbolFlag.Const || constSymbol.Type != DatSymbolType.Int) { throw new Exception($"Expected integer constant: {arraySizeContext.GetText()}"); } arrIndex = (uint)(int)constSymbol.Content[0]; } symbol = SymbolBuilder.BuildArrOfVariables(parameterName, parameterType.Value, arrIndex, location); } else { if (_assemblyBuilder.IsCurrentlyParsingExternals) { symbol = SymbolBuilder.BuildExternalParameter(parameterName, parameterType.Value, location, parentIndex); } else { symbol = SymbolBuilder.BuildParameter(parameterName, parameterType.Value, location, parentIndex); } } _assemblyBuilder.AddSymbol(symbol); }
private Dictionary <string, int> GetLabelToAddressDict(BaseExecBlockContext execBlock) { Dictionary <string, int> labelToAddress = new Dictionary <string, int>(); foreach (var instruction in execBlock.Body) { switch (instruction) { case PushArrayVar _: { _currentAddress += 6; break; } case JumpToLabel _: case SymbolInstruction _: case ValueInstruction _: { _currentAddress += 5; break; } case ParamLessInstruction _: { _currentAddress += 1; break; } case AssemblyLabel assemblyLabel: { labelToAddress[assemblyLabel.Label] = _currentAddress; break; } } } return(labelToAddress); }
public void ExecBlockStart(DatSymbol symbol, ExecBlockType blockType) { switch (blockType) { case ExecBlockType.Function: ActiveExecBlock = new FunctionBlockContext(symbol); break; case ExecBlockType.Instance: ActiveExecBlock = new InstanceBlockContext(symbol); break; case ExecBlockType.Prototype: ActiveExecBlock = new PrototypeBlockContext(symbol); break; default: throw new NotImplementedException(); } _activeContext = ActiveExecBlock; ExecBlocks.Add(ActiveExecBlock); }
public void ExecBlockEnd() { ActiveExecBlock = null; ActiveContextEnd(); }
public void SharedBlockStart(List <DatSymbol> symbols) { ActiveExecBlock = new SharedExecBlockContext(symbols); _activeContext = ActiveExecBlock; ExecBlocks.Add(ActiveExecBlock); }
public override void EnterConstDef([NotNull] DaedalusParser.ConstDefContext context) { _assemblyBuilder.IsInsideConstDef = true; var typeName = context.typeReference().GetText(); var type = DatSymbolTypeFromString(typeName); if (type == DatSymbolType.Func) { type = DatSymbolType.Int; } for (int i = 0; i < context.ChildCount; i++) { var constContext = context.GetChild(i); if (constContext is TerminalNodeImpl) { continue; // skips ',' } if (constContext is DaedalusParser.ConstValueDefContext constValueContext) { var name = constValueContext.nameNode().GetText(); if (_assemblyBuilder.IsContextInsideExecBlock()) { BaseExecBlockContext baseExecBlock = _assemblyBuilder.ExecBlocks.Last(); string execBlockName = baseExecBlock.GetSymbol().Name; name = $"{execBlockName}.{name}"; } var location = GetLocation(context); var assignmentExpression = constValueContext.constValueAssignment().expressionBlock().expression(); var value = EvaluatorHelper.EvaluateConst(assignmentExpression, _assemblyBuilder, type); var symbol = SymbolBuilder.BuildConst(name, type, value, location); // TODO : Validate params _assemblyBuilder.AddSymbol(symbol); continue; } if (constContext is DaedalusParser.ConstArrayDefContext constArrayContext) { _assemblyBuilder.ErrorContext.Context = constArrayContext; var name = constArrayContext.nameNode().GetText(); var location = GetLocation(context); int declaredSize = 0; bool compareDeclaredSizeAndElementsCount = true; try { _assemblyBuilder.ErrorContext.Context = constArrayContext.arraySize(); declaredSize = EvaluatorHelper.EvaluteArraySize(constArrayContext.arraySize(), _assemblyBuilder); } catch (System.ArgumentNullException) { compareDeclaredSizeAndElementsCount = false; } if (declaredSize == 0 && compareDeclaredSizeAndElementsCount) { compareDeclaredSizeAndElementsCount = false; _assemblyBuilder.Errors.Add( new InvalidArraySizeError( _assemblyBuilder.ErrorContext, name, declaredSize ) ); } var elements = constArrayContext.constArrayAssignment().expressionBlock() .Select(expr => EvaluatorHelper.EvaluateConst(expr.expression(), _assemblyBuilder, type)) .ToArray(); if (compareDeclaredSizeAndElementsCount && declaredSize != elements.Length) { _assemblyBuilder.Errors.Add( new InconsistentArraySizeError( _assemblyBuilder.ErrorContext, name, declaredSize, elements.Length ) ); } var symbol = SymbolBuilder.BuildArrOfConst(name, type, elements, location); // TODO : Validate params _assemblyBuilder.AddSymbol(symbol); } } }
private List <DatToken> GetTokens(BaseExecBlockContext execBlock) { List <DatToken> tokens = new List <DatToken>(); Dictionary <string, int> labelToAddress = GetLabelToAddressDict(execBlock); foreach (var instruction in execBlock.Body) { if (instruction is AssemblyLabel) { continue; } int? intParam = null; byte?byteParam = null; switch (instruction) { case Call call: { intParam = call.Symbol.FirstTokenAddress; break; } case PushArrayVar pushArrVar: { intParam = pushArrVar.Symbol.Index; byteParam = (byte)pushArrVar.Index; break; } case JumpToLabel jumpToLabel: { intParam = labelToAddress[jumpToLabel.Label]; break; } case SymbolInstruction symbolInstruction: { intParam = symbolInstruction.Symbol.Index; break; } case ValueInstruction valueInstruction: { intParam = (int)valueInstruction.Value; break; } case AddressInstruction addressInstruction: // TODO check if there is any possibility for this { intParam = addressInstruction.Address; break; } } string tokenName = instruction.GetType().Name; if (instruction is JumpToLabel) { tokenName = tokenName.Substring(0, tokenName.Length - "ToLabel".Length); } DatTokenType datTokenType = Enum.Parse <DatTokenType>(tokenName); tokens.Add(new DatToken { TokenType = datTokenType, IntParam = intParam, ByteParam = byteParam }); } return(tokens); }