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);
        }
Пример #3
0
        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);
        }