public static void EndStructDeclaration(this CompilerIO self, StructTypeBuilder builder, Slice slice, bool isPublic) { var name = CompilerHelper.GetSlice(self, slice); var result = builder.Build(name, isPublic, self.structTypesStartIndex, out var index); self.CheckStructBuild(result, slice, name); }
// VARIABLES public static int AddLocalVariable(this CompilerIO self, Slice slice, ValueType type, VariableFlags flags) { self.DebugPushLocalVariableName( (flags & VariableFlags.Iteration) != 0 ? "it" : CompilerHelper.GetSlice(self, slice) ); byte stackIndex = 0; if (self.localVariables.count > 0) { var lastVar = self.localVariables.buffer[self.localVariables.count - 1]; stackIndex = (byte)(lastVar.stackIndex + lastVar.type.GetSize(self.chunk)); } if (self.parser.tokenizer.source[slice.index] == '_') { flags |= VariableFlags.Used | VariableFlags.Changed; } self.localVariables.PushBack(new LocalVariable( slice, stackIndex, type, flags )); return(self.localVariables.count - 1); }
public static void EndScope(this CompilerIO self, Scope scope, int sizeLeftOnStack) { self.scopeDepth -= 1; for (var i = scope.localVariablesStartIndex; i < self.localVariables.count; i++) { var variable = self.localVariables.buffer[i]; if (!variable.IsUsed) { self.AddSoftError(variable.slice, "Unused variable '{0}'", CompilerHelper.GetSlice(self, variable.slice)); } if (variable.IsMutable && !variable.IsChanged) { self.AddSoftError(variable.slice, "Mutable variable '{0}' never changes", CompilerHelper.GetSlice(self, variable.slice)); } } var localCount = self.localVariables.count - scope.localVariablesStartIndex; if (localCount == 0) { return; } var localVarsSize = 0; for (var i = scope.localVariablesStartIndex; i < self.localVariables.count; i++) { var type = self.localVariables.buffer[i].type; localVarsSize += type.GetSize(self.chunk); } if (sizeLeftOnStack > 0) { self.EmitInstruction(Instruction.Move); self.EmitByte((byte)localVarsSize); self.EmitByte((byte)sizeLeftOnStack); } else { self.EmitPop(localVarsSize); } self.localVariables.count -= localCount; self.DebugEmitPopTypes((byte)localCount); self.DebugPopLocalVariableNames((byte)localCount); }
public static int EndFunctionDeclaration(this CompilerIO self, FunctionTypeBuilder builder, Slice slice, bool isPublic, bool hasBody) { var name = CompilerHelper.GetSlice(self, slice); var result = builder.Build(out var index); var functionIndex = -1; if (self.CheckFunctionBuild(result, slice)) { switch (self.chunk.AddFunction(name, isPublic, index, hasBody, slice, self.functionsStartIndex, out functionIndex)) { case ByteCodeChunk.AddFunctionResult.AlreadyDefined: self.AddSoftError(slice, "Function '{0}' is already defined", name); break; case ByteCodeChunk.AddFunctionResult.VisibilityMismatch: { if (self.ResolveToFunctionIndex(slice, out int prototypeIndex)) { var prototypeIsPublic = self.chunk.functions.buffer[prototypeIndex].isPublic; self.AddSoftError( slice, "Visibility mismatch between function '{0}' prototype and its body. Expected {1}. Got {2}", name, prototypeIsPublic ? "'pub'" : "no 'pub'", isPublic ? "'pub'" : "no 'pub'" ); } else { self.AddSoftError(slice, "Visibility mismatch between function '{0}' prototype and its body", name); } break; } case ByteCodeChunk.AddFunctionResult.TypeMismatch: { if (self.ResolveToFunctionIndex(slice, out int prototypeIndex)) { var typeIndex = self.chunk.functions.buffer[prototypeIndex].typeIndex; var prototypeType = new ValueType(TypeKind.Function, typeIndex); var functionType = new ValueType(TypeKind.Function, index); self.AddSoftError( slice, "Type mismatch between function '{0}' prototype and its body. Expected {1}. Got {2}", name, prototypeType.ToString(self.chunk), functionType.ToString(self.chunk) ); } else { self.AddSoftError(slice, "Type mismatch between function '{0}' prototype and its body", name); } break; } default: break; } } if (functionIndex < 0) { functionIndex = self.chunk.functions.count; if (self.chunk.functionTypes.count < ushort.MaxValue) { self.chunk.functionTypes.PushBack(new FunctionType(new Slice(), new ValueType(TypeKind.Unit), 0)); } var typeIndex = self.chunk.functionTypes.count - 1; self.chunk.functions.PushBack(new Function(name, isPublic, -slice.index, (ushort)typeIndex)); } return(functionIndex); }