Example #1
0
 /// <summary>
 /// スニペット変数を追加する
 /// </summary>
 /// <param name="id">変数名</param>
 /// <param name="toolTip">説明</param>
 /// <param name="_default">デフォルト値</param>
 /// <param name="function">適用する関数</param>
 public void AddDeclaration(string id, string toolTip, string _default, Function?function)
 {
     if (Declarations is null)
     {
         Declarations = new List <Literal>();
     }
     Declarations.Add(new Literal(id, toolTip, _default, function));
 }
Example #2
0
        /// <summary>
        /// Parses arguments for a function call. If <paramref name="usingParentheses"/>
        /// is true, assumes opening parenthesis has been read and reads up to and
        /// including the closing parenthesis. Returns false on error.
        /// </summary>
        /// <param name="function">Function being called. May be null for user
        /// functions. Used to verify argument count for intrinsic functions.</param>
        private bool ParseFunctionArguments(Function?function, bool usingParentheses)
        {
            Token token;
            int   count = 0;

            // Save position and write placeholder for argument count
            int argumentCountIP = Writer.Write(0);

            if (ParseExpression(false))
            {
                count++;
                token = Lexer.GetNext();
                while (token.Type == TokenType.Comma)
                {
                    if (!ParseExpression())
                    {
                        return(false);
                    }
                    count++;
                    token = Lexer.GetNext();
                }
            }
            else
            {
                token = Lexer.GetNext();
            }

            if (usingParentheses)
            {
                if (token.Type != TokenType.RightParen)
                {
                    Error(ErrorCode.ExpectedRightParen, token);
                    return(false);
                }
            }
            else
            {
                Lexer.UngetToken(token);
            }

            // Enforce argument count for intrinsic functions
            // (May be null for user functions not yet defined)
            if (function is IntrinsicFunction intrinsicFunction)
            {
                if (!intrinsicFunction.IsParameterCountValid(count, out string?error))
                {
                    Error(ErrorCode.WrongNumberOfArguments, error);
                    return(false);
                }
            }
            // Fixup argument count
            Writer.WriteAt(argumentCountIP, count);
            return(true);
        }
Example #3
0
        /// <summary>
        /// Function.ClassName以外対応
        /// </summary>
        /// <param name="id"></param>
        /// <param name="function">Function.ClassName以外を指定すること</param>
        public Literal(string id, Function?function, string functionValue)
        {
            string _default = null;

            if (function == MinteaCore.SnippetGenerator.Function.GenerateSwitchCases)
            {
                _default = ":default";
            }
            Initialize(id, null, _default);
            Function      = function;
            FunctionValue = functionValue;
        }
Example #4
0
        public Function?FindFunction(int address)
        {
            var      idx    = Search(_functions, new Function(address, 0), FunctionAddressComparer);
            Function?result = null;

            if (idx >= 0 && idx < _functions.Count)
            {
                result = _functions[idx];
            }

            return(result);
        }
Example #5
0
        /// <summary>
        /// Creates a new function with the given name
        /// </summary>
        /// <param name="functionName">The function's name. If null will get random name</param>
        /// <param name="setting">The settings for how to write the file</param>
        /// <returns>The newly created function</returns>
        public Function Function(string?functionName = null, BaseFile.WriteSetting setting = BaseFile.WriteSetting.LockedAuto)
        {
            if (string.IsNullOrWhiteSpace(functionName))
            {
                return(new Function(this, null, setting));
            }

            Function?returnFunction = (Function?)GetFile("function", functionName);

            if (returnFunction is null)
            {
                return(new Function(this, functionName, setting));
            }
            else
            {
                return(returnFunction);
            }
        }
Example #6
0
        /// <summary>
        /// Parses a symbol. Expected to be either a label, an assignment, a function
        /// definition, or function call.
        /// </summary>
        private void ParseSymbol(Token token)
        {
            Token nextToken = Lexer.GetNext();

            switch (nextToken.Type)
            {
            case TokenType.Colon:
                // Label definition
                if (!InFunction)
                {
                    Error(ErrorCode.CodeOutsideFunction, token);
                    NextLine();
                    return;
                }
                AddLabel(token.Value, Writer.IP);
                // Allow another statement on same line
                break;

            case TokenType.LeftBracket:
                // Assignment to list item
                if (!InFunction)
                {
                    Error(ErrorCode.CodeOutsideFunction, token);
                    NextLine();
                    return;
                }

                Writer.Write(ByteCode.AssignListVariableMulti, GetVariableId(token.Value));
                int subscriptsIP = Writer.Write(0);        //
                int subscripts   = 0;

                do
                {
                    // Parse list index
                    if (!ParseExpression())
                    {
                        return;
                    }
                    token = Lexer.GetNext();
                    if (token.Type != TokenType.RightBracket)
                    {
                        Error(ErrorCode.ExpectedRightBracket, token);
                        NextLine();
                        return;
                    }
                    subscripts++;

                    // Get next token
                    token = Lexer.GetNext();
                } while (token.Type == TokenType.LeftBracket);

                // Set index count
                Writer.WriteAt(subscriptsIP, subscripts);

                if (token.Type != TokenType.Equal)
                {
                    Error(ErrorCode.ExpectedEquals, token);
                    NextLine();
                    return;
                }

                // Parse expression
                if (!ParseExpression())
                {
                    return;
                }
                VerifyEndOfLine();
                break;

            case TokenType.Equal:
                // Assignment
                if (!InFunction)
                {
                    Error(ErrorCode.CodeOutsideFunction, token);
                    NextLine();
                    return;
                }
                // Test for read-only
                int varId = GetVariableId(token.Value);
                if (IsReadOnly(varId))
                {
                    Error(ErrorCode.AssignToReadOnlyVariable, token);
                    NextLine();
                    return;
                }
                Writer.Write(ByteCode.Assign, varId);
                if (!ParseExpression())
                {
                    return;
                }
                VerifyEndOfLine();
                break;

            default:
                if (InFunction)
                {
                    // Function call
                    int      functionId = GetFunctionId(token.Value);
                    Function?function   = Functions[functionId];
                    Writer.Write(ByteCode.ExecFunction, functionId);
                    // Next token might be part of argument expression
                    Lexer.UngetToken(nextToken);
                    if (!ParseFunctionArguments(function, false))
                    {
                        return;
                    }
                    VerifyEndOfLine();
                }
                else
                {
                    // Function definition requires parentheses
                    if (nextToken.Type != TokenType.LeftParen)
                    {
                        Error(ErrorCode.ExpectedLeftParen, nextToken);
                        break;
                    }
                    // Create function
                    var function = new CompileTimeUserFunction(token.Value, Writer.IP);
                    // Parse and add parameters
                    if (!ParseFunctionParameters(function))
                    {
                        return;
                    }
                    // Add user function
                    AddUserFunction(token.Value, function);

                    InHeader        = false;
                    CurrentFunction = function;

                    token = Lexer.GetNextSkipNewLines();
                    if (token.Type != TokenType.LeftBrace)
                    {
                        Error(ErrorCode.ExpectedLeftBrace, token);
                        return;
                    }

                    // Parse statements in function
                    while (ParseStatement())
                    {
                        ;
                    }

                    token = Lexer.GetNext();
                    if (token.Type != TokenType.RightBrace)
                    {
                        Error(ErrorCode.ExpectedRightBrace);
                        return;
                    }

                    // Write return (no return expression)
                    Writer.Write(ByteCode.Return, 0);

                    // Check for undefined labels
                    foreach (var labelInfo in function.Labels.GetKeyValuePairs())
                    {
                        if (labelInfo.Value.IP == null)
                        {
                            Error(ErrorCode.LabelNotDefined, labelInfo.Key.MakeQuoted());
                            return;
                        }
                    }
                    CurrentFunction = null;
                }
                break;
            }
        }
Example #7
0
        // defaultはリファレンスに説明が書いてないので書かない

        /// <summary>
        /// Function.ClassNameのみ対応
        /// </summary>
        /// <param name="id"></param>
        /// <param name="toolTip"></param>
        /// <param name="_default"></param>
        /// <param name="function">Function.ClassNameを指定すること</param>
        public Literal(string id, string toolTip, string _default, Function?function = MinteaCore.SnippetGenerator.Function.ClassName)
        {
            Initialize(id, toolTip, _default);
            Function      = function;
            FunctionValue = string.Empty;
        }
Example #8
0
 protected Message(FrameHeader header, MessageType?type = null, Function?function = null)
 {
     Header   = header;
     Type     = type;
     Function = function;
 }
Example #9
0
        public void Execute(string function)
        {
            // get the current function
            Function?currentFunction = null;

            foreach (Function f in _functions)
            {
                if (f.Name == function)
                {
                    currentFunction = f;
                    break;
                }
            }

            if (currentFunction.HasValue == false)
            {
                throw new ArgumentException("Function not found: " + function);
            }

            int instructionPtr = 0;

            byte[] code       = currentFunction.Value.Code;
            uint   codeOffset = currentFunction.Value.CodeOffset;

            while (instructionPtr < code.Length)
            {
                byte        op = code[instructionPtr++];
                int         param;
                Parameter[] functionParams;

                switch (op)
                {
                case 0x00:     // SitnSpin
                    // do nothing
                    break;

                case 0x02:     // CallSysFunctionV
                    param          = getIntFromBytes(code, ref instructionPtr);
                    functionParams = buildParameterArray();
                    SheepMachine.CallVoidSystemFunction(Imports[param].Name, functionParams);
                    _state.PushStack(0);
                    break;

                case 0x03:     // CallSysFunctionI
                    param          = getIntFromBytes(code, ref instructionPtr);
                    functionParams = buildParameterArray();
                    _state.PushStack(SheepMachine.CallIntSystemFunction(Imports[param].Name, functionParams));
                    break;

                case 0x05:     // CallSysFunctionS
                    param          = getIntFromBytes(code, ref instructionPtr);
                    functionParams = buildParameterArray();
                    SheepMachine.CallStringSystemFunction(Imports[param].Name, functionParams);
                    _state.PushString(0);
                    break;

                case 0x06:     // Branch
                    param          = getIntFromBytes(code, ref instructionPtr);
                    instructionPtr = param - (int)codeOffset;
                    break;

                case 0x08:     // BranchIfZero
                    param = getIntFromBytes(code, ref instructionPtr);
                    if (_state.PeekStack().Type != ParameterType.Integer)
                    {
                        throw new InvalidOperationException("stack is bad");
                    }
                    if (_state.PopStack().Integer == 0)
                    {
                        instructionPtr = param - (int)codeOffset;
                    }
                    break;

                case 0x09:     // BeginWait
                    // do nothing
                    break;

                case 0x0A:     // EndWait
                    // do nothing
                    break;

                case 0x0B:     // ReturnV
                    return;

                case 0x13:     // PushI
                    param = getIntFromBytes(code, ref instructionPtr);
                    _state.PushStack(param);
                    break;

                case 0x15:     // PushS
                    param = getIntFromBytes(code, ref instructionPtr);
                    _state.PushString(param);
                    break;

                case 0x16:     // Pop
                    _state.PopStack();
                    break;

                case 0x21:     // IsEqualI
                    if (_state.PeekStack().Type != ParameterType.Integer ||
                        _state.PeekStack().Type != ParameterType.Integer)
                    {
                        throw new InvalidOperationException("IsLessI found two non-integers on the stack");
                    }
                    if (_state.PopStack().Integer == _state.PopStack().Integer)
                    {
                        _state.PushStack(1);
                    }
                    else
                    {
                        _state.PushStack(0);
                    }
                    break;

                case 0x27:     // IsLessI
                    if (_state.PeekStack().Type != ParameterType.Integer ||
                        _state.PeekStack().Type != ParameterType.Integer)
                    {
                        throw new InvalidOperationException("IsLessI found two non-integers on the stack");
                    }
                    if (_state.PopStack().Integer >= _state.PopStack().Integer)
                    {
                        _state.PushStack(1);
                    }
                    else
                    {
                        _state.PushStack(0);
                    }
                    break;

                case 0x2D:
                    param = getIntFromBytes(code, ref instructionPtr);
                    _state.PushStack((float)param);
                    break;

                case 0x30:
                    // do nothing
                    break;

                case 0x31:
                    // do nothing
                    break;

                case 0x33:     // GetString
                {
                    if (_state.PeekStack().Type != ParameterType.String)
                    {
                        throw new InvalidOperationException("GetString failed because value on stack isn't a string");
                    }

                    param = _state.PopStack().Integer;
                    Parameter p = new Parameter();
                    p.Type    = ParameterType.String;
                    p.Integer = param;
                    p.String  = Constants[_constantOffsetIndexMap[param]];

                    _state.PushStack(p);
                }
                break;

                default:
                    throw new NotImplementedException("Instruction " +
                                                      op.ToString("X") + " not implemented");
                }
            }

            return;
        }