|
2 | 2 |
|
3 | 3 | #pragma once
|
4 | 4 |
|
5 |
| -#include <vector> |
6 |
| -#include <memory> |
7 | 5 | #include <unordered_set>
|
| 6 | +#include <vector> |
8 | 7 |
|
9 | 8 | #include "global.h"
|
10 | 9 | #include "spimpl.h"
|
11 |
| -#include "virtualmachine.h" |
12 |
| -#include "value.h" |
13 | 10 |
|
14 | 11 | namespace libscratchcpp
|
15 | 12 | {
|
16 | 13 |
|
| 14 | +class CompilerContext; |
17 | 15 | class IEngine;
|
18 |
| -class Block; |
19 |
| -class Input; |
20 |
| -class InputValue; |
21 |
| -class Field; |
| 16 | +class Target; |
| 17 | +class ExecutableCode; |
| 18 | +class CompilerValue; |
| 19 | +class CompilerConstant; |
| 20 | +class CompilerLocalVariable; |
22 | 21 | class Variable;
|
23 | 22 | class List;
|
| 23 | +class Input; |
| 24 | +class Field; |
24 | 25 | class BlockPrototype;
|
25 |
| -class Entity; |
26 | 26 | class CompilerPrivate;
|
27 | 27 |
|
28 |
| -/*! \brief The Compiler class provides an API for compiling scripts of targets to bytecode. */ |
| 28 | +/*! \brief The Compiler class provides API for compiling Scratch scripts. */ |
29 | 29 | class LIBSCRATCHCPP_EXPORT Compiler
|
30 | 30 | {
|
31 | 31 | public:
|
32 |
| - enum class SubstackType |
| 32 | + enum class StaticType |
33 | 33 | {
|
34 |
| - Loop, |
35 |
| - IfStatement |
| 34 | + Void, |
| 35 | + Number, |
| 36 | + Bool, |
| 37 | + String, |
| 38 | + Unknown |
36 | 39 | };
|
37 | 40 |
|
38 |
| - Compiler(IEngine *engine, Target *target = nullptr); |
39 |
| - Compiler(const Compiler &) = delete; |
40 |
| - |
41 |
| - void init(); |
42 |
| - void compile(std::shared_ptr<Block> topLevelBlock); |
43 |
| - void end(); |
| 41 | + using ArgTypes = std::vector<StaticType>; |
| 42 | + using Args = std::vector<CompilerValue *>; |
44 | 43 |
|
45 |
| - const std::vector<unsigned int> &bytecode() const; |
46 |
| - const std::vector<unsigned int> &hatPredicateBytecode() const; |
| 44 | + Compiler(CompilerContext *ctx); |
| 45 | + Compiler(IEngine *engine, Target *target); |
| 46 | + Compiler(const Compiler &) = delete; |
47 | 47 |
|
48 | 48 | IEngine *engine() const;
|
49 | 49 | Target *target() const;
|
50 |
| - |
51 |
| - const std::vector<InputValue *> &constInputValues() const; |
52 |
| - std::vector<Value> constValues() const; |
53 |
| - |
54 |
| - const std::vector<Variable *> &variables() const; |
55 |
| - std::vector<Value *> variablePtrs() const; |
56 |
| - |
57 |
| - const std::vector<List *> &lists() const; |
58 |
| - |
59 |
| - void addInstruction(vm::Opcode opcode, const std::initializer_list<unsigned int> &args = {}); |
60 |
| - void addInput(Input *input); |
61 |
| - void addInput(int id); |
62 |
| - void addConstValue(const Value &value); |
63 |
| - void addFunctionCall(BlockFunc f); |
64 |
| - void addProcedureArg(const std::string &procCode, const std::string &argName); |
65 |
| - void moveToSubstack(std::shared_ptr<Block> substack1, std::shared_ptr<Block> substack2, SubstackType type); |
66 |
| - void moveToSubstack(std::shared_ptr<Block> substack, SubstackType type); |
| 50 | + std::shared_ptr<Block> block() const; |
| 51 | + |
| 52 | + std::shared_ptr<ExecutableCode> compile(std::shared_ptr<Block> startBlock); |
| 53 | + void preoptimize(); |
| 54 | + |
| 55 | + CompilerValue *addFunctionCall(const std::string &functionName, StaticType returnType = StaticType::Void, const ArgTypes &argTypes = {}, const Args &args = {}); |
| 56 | + CompilerValue *addTargetFunctionCall(const std::string &functionName, StaticType returnType = StaticType::Void, const ArgTypes &argTypes = {}, const Args &args = {}); |
| 57 | + CompilerValue *addFunctionCallWithCtx(const std::string &functionName, StaticType returnType = StaticType::Void, const ArgTypes &argTypes = {}, const Args &args = {}); |
| 58 | + CompilerConstant *addConstValue(const Value &value); |
| 59 | + CompilerValue *addLoopIndex(); |
| 60 | + CompilerValue *addLocalVariableValue(CompilerLocalVariable *variable); |
| 61 | + CompilerValue *addVariableValue(Variable *variable); |
| 62 | + CompilerValue *addListContents(List *list); |
| 63 | + CompilerValue *addListItem(List *list, CompilerValue *index); |
| 64 | + CompilerValue *addListItemIndex(List *list, CompilerValue *item); |
| 65 | + CompilerValue *addListContains(List *list, CompilerValue *item); |
| 66 | + CompilerValue *addListSize(List *list); |
| 67 | + CompilerValue *addProcedureArgument(const std::string &name); |
| 68 | + |
| 69 | + CompilerValue *addInput(const std::string &name); |
| 70 | + CompilerValue *addInput(Input *input); |
| 71 | + |
| 72 | + CompilerValue *createAdd(CompilerValue *operand1, CompilerValue *operand2); |
| 73 | + CompilerValue *createSub(CompilerValue *operand1, CompilerValue *operand2); |
| 74 | + CompilerValue *createMul(CompilerValue *operand1, CompilerValue *operand2); |
| 75 | + CompilerValue *createDiv(CompilerValue *operand1, CompilerValue *operand2); |
| 76 | + |
| 77 | + CompilerValue *createRandom(CompilerValue *from, CompilerValue *to); |
| 78 | + CompilerValue *createRandomInt(CompilerValue *from, CompilerValue *to); |
| 79 | + |
| 80 | + CompilerValue *createCmpEQ(CompilerValue *operand1, CompilerValue *operand2); |
| 81 | + CompilerValue *createCmpGT(CompilerValue *operand1, CompilerValue *operand2); |
| 82 | + CompilerValue *createCmpLT(CompilerValue *operand1, CompilerValue *operand2); |
| 83 | + |
| 84 | + CompilerValue *createStrCmpEQ(CompilerValue *string1, CompilerValue *string2, bool caseSensitive = false); |
| 85 | + |
| 86 | + CompilerValue *createAnd(CompilerValue *operand1, CompilerValue *operand2); |
| 87 | + CompilerValue *createOr(CompilerValue *operand1, CompilerValue *operand2); |
| 88 | + CompilerValue *createNot(CompilerValue *operand); |
| 89 | + |
| 90 | + CompilerValue *createMod(CompilerValue *num1, CompilerValue *num2); |
| 91 | + CompilerValue *createRound(CompilerValue *num); |
| 92 | + CompilerValue *createAbs(CompilerValue *num); |
| 93 | + CompilerValue *createFloor(CompilerValue *num); |
| 94 | + CompilerValue *createCeil(CompilerValue *num); |
| 95 | + CompilerValue *createSqrt(CompilerValue *num); |
| 96 | + CompilerValue *createSin(CompilerValue *num); |
| 97 | + CompilerValue *createCos(CompilerValue *num); |
| 98 | + CompilerValue *createTan(CompilerValue *num); |
| 99 | + CompilerValue *createAsin(CompilerValue *num); |
| 100 | + CompilerValue *createAcos(CompilerValue *num); |
| 101 | + CompilerValue *createAtan(CompilerValue *num); |
| 102 | + CompilerValue *createLn(CompilerValue *num); |
| 103 | + CompilerValue *createLog10(CompilerValue *num); |
| 104 | + CompilerValue *createExp(CompilerValue *num); |
| 105 | + CompilerValue *createExp10(CompilerValue *num); |
| 106 | + |
| 107 | + CompilerValue *createSelect(CompilerValue *cond, CompilerValue *trueValue, CompilerValue *falseValue, Compiler::StaticType valueType); |
| 108 | + |
| 109 | + CompilerLocalVariable *createLocalVariable(Compiler::StaticType type); |
| 110 | + void createLocalVariableWrite(CompilerLocalVariable *variable, CompilerValue *value); |
| 111 | + |
| 112 | + void createVariableWrite(Variable *variable, CompilerValue *value); |
| 113 | + |
| 114 | + void createListClear(List *list); |
| 115 | + void createListRemove(List *list, CompilerValue *index); |
| 116 | + void createListAppend(List *list, CompilerValue *item); |
| 117 | + void createListInsert(List *list, CompilerValue *index, CompilerValue *item); |
| 118 | + void createListReplace(List *list, CompilerValue *index, CompilerValue *item); |
| 119 | + |
| 120 | + void beginIfStatement(CompilerValue *cond); |
| 121 | + void beginElseBranch(); |
| 122 | + void endIf(); |
| 123 | + |
| 124 | + void beginWhileLoop(CompilerValue *cond); |
| 125 | + void beginRepeatUntilLoop(CompilerValue *cond); |
| 126 | + void beginLoopCondition(); |
| 127 | + void endLoop(); |
| 128 | + |
| 129 | + void moveToIf(CompilerValue *cond, std::shared_ptr<Block> substack); |
| 130 | + void moveToIfElse(CompilerValue *cond, std::shared_ptr<Block> substack1, std::shared_ptr<Block> substack2); |
| 131 | + void moveToRepeatLoop(CompilerValue *count, std::shared_ptr<Block> substack); |
| 132 | + void moveToWhileLoop(CompilerValue *cond, std::shared_ptr<Block> substack); |
| 133 | + void moveToRepeatUntilLoop(CompilerValue *cond, std::shared_ptr<Block> substack); |
67 | 134 | void warp();
|
68 | 135 |
|
69 |
| - Input *input(int id) const; |
70 |
| - Field *field(int id) const; |
71 |
| - std::shared_ptr<Block> inputBlock(int id) const; |
72 |
| - unsigned int variableIndex(std::shared_ptr<Entity> varEntity); |
73 |
| - unsigned int listIndex(std::shared_ptr<Entity> listEntity); |
74 |
| - unsigned int constIndex(InputValue *value); |
75 |
| - unsigned int procedureIndex(const std::string &proc); |
76 |
| - long procedureArgIndex(const std::string &procCode, const std::string &argName); |
77 |
| - |
78 |
| - const std::vector<std::string> &procedures() const; |
| 136 | + void createYield(); |
| 137 | + void createStop(); |
79 | 138 |
|
80 |
| - const std::shared_ptr<Block> &block() const; |
81 |
| - void setBlock(std::shared_ptr<Block> block); |
| 139 | + void createProcedureCall(BlockPrototype *prototype, const Compiler::Args &args); |
82 | 140 |
|
83 |
| - BlockPrototype *procedurePrototype() const; |
84 |
| - void setProcedurePrototype(BlockPrototype *prototype); |
| 141 | + Input *input(const std::string &name) const; |
| 142 | + Field *field(const std::string &name) const; |
85 | 143 |
|
86 | 144 | const std::unordered_set<std::string> &unsupportedBlocks() const;
|
87 | 145 |
|
| 146 | + static std::shared_ptr<CompilerContext> createContext(IEngine *engine, Target *target); |
| 147 | + |
88 | 148 | private:
|
89 | 149 | spimpl::unique_impl_ptr<CompilerPrivate> impl;
|
90 | 150 | };
|
|
0 commit comments