Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 0 additions & 28 deletions .github/workflows/utests-llvm.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/utests-minimal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
submodules: true

- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DLIBSCRATCHCPP_BUILD_UNIT_TESTS=ON -DLIBSCRATCHCPP_AUDIO_SUPPORT=OFF -DLIBSCRATCHCPP_NETWORK_SUPPORT=OFF -DLIBSCRATCHCPP_COMPUTED_GOTO=OFF
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DLIBSCRATCHCPP_BUILD_UNIT_TESTS=ON -DLIBSCRATCHCPP_AUDIO_SUPPORT=OFF -DLIBSCRATCHCPP_NETWORK_SUPPORT=OFF

- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j$(nproc --all)
Expand Down
54 changes: 14 additions & 40 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,28 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)

option(LIBSCRATCHCPP_BUILD_UNIT_TESTS "Build unit tests" ON)
option(LIBSCRATCHCPP_NETWORK_SUPPORT "Support for downloading projects" ON)
option(LIBSCRATCHCPP_COMPUTED_GOTO "Support for computed goto" ON)
option(LIBSCRATCHCPP_USE_LLVM "Compile scripts to LLVM IR (work in progress)" OFF)
option(LIBSCRATCHCPP_PRINT_LLVM_IR "Print LLVM IR of compiled Scratch scripts (for debugging)" OFF)

if (NOT (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"))
# Computed goto not supported on anything except GCC
set(LIBSCRATCHCPP_COMPUTED_GOTO OFF CACHE BOOL "" FORCE)
endif()

add_library(scratchcpp SHARED)
add_subdirectory(src)
include_directories(src) # TODO: Remove this line
include_directories(include)

if (LIBSCRATCHCPP_COMPUTED_GOTO)
target_compile_definitions(scratchcpp PRIVATE ENABLE_COMPUTED_GOTO)
endif()

target_sources(scratchcpp
PUBLIC
include/scratchcpp/global.h
include/scratchcpp/project.h
include/scratchcpp/scratchconfiguration.h
include/scratchcpp/iengine.h
include/scratchcpp/iextension.h
include/scratchcpp/compiler.h
include/scratchcpp/compilercontext.h
include/scratchcpp/compilervalue.h
include/scratchcpp/compilerconstant.h
include/scratchcpp/compilerlocalvariable.h
include/scratchcpp/executablecode.h
include/scratchcpp/executioncontext.h
include/scratchcpp/promise.h
include/scratchcpp/thread.h
include/scratchcpp/asset.h
include/scratchcpp/costume.h
Expand All @@ -48,7 +45,6 @@ target_sources(scratchcpp
include/scratchcpp/field.h
include/scratchcpp/script.h
include/scratchcpp/broadcast.h
include/scratchcpp/virtualmachine.h
include/scratchcpp/blockprototype.h
include/scratchcpp/block.h
include/scratchcpp/istagehandler.h
Expand All @@ -67,31 +63,11 @@ target_sources(scratchcpp
include/scratchcpp/comment.h
include/scratchcpp/monitor.h
include/scratchcpp/imonitorhandler.h
include/scratchcpp/test/scriptbuilder.h
)

if (LIBSCRATCHCPP_USE_LLVM)
target_compile_definitions(scratchcpp PUBLIC USE_LLVM)
target_sources(scratchcpp
PUBLIC
include/scratchcpp/dev/compiler.h
include/scratchcpp/dev/compilercontext.h
include/scratchcpp/dev/compilervalue.h
include/scratchcpp/dev/compilerconstant.h
include/scratchcpp/dev/compilerlocalvariable.h
include/scratchcpp/dev/executablecode.h
include/scratchcpp/dev/executioncontext.h
include/scratchcpp/dev/promise.h
include/scratchcpp/dev/test/scriptbuilder.h
)

if(LIBSCRATCHCPP_PRINT_LLVM_IR)
target_compile_definitions(scratchcpp PRIVATE PRINT_LLVM_IR)
endif()
else()
target_sources(scratchcpp
PUBLIC
include/scratchcpp/compiler.h
)
if(LIBSCRATCHCPP_PRINT_LLVM_IR)
target_compile_definitions(scratchcpp PRIVATE PRINT_LLVM_IR)
endif()

include(FetchContent)
Expand Down Expand Up @@ -123,11 +99,9 @@ if (LIBSCRATCHCPP_NETWORK_SUPPORT)
target_compile_definitions(scratchcpp PRIVATE LIBSCRATCHCPP_NETWORK_SUPPORT)
endif()

if (LIBSCRATCHCPP_USE_LLVM)
include(build/HunterPackages.cmake)
include(build/LLVM.cmake)
target_link_libraries(scratchcpp PRIVATE LLVM)
endif()
include(build/HunterPackages.cmake)
include(build/LLVM.cmake)
target_link_libraries(scratchcpp PRIVATE LLVM)

target_compile_definitions(scratchcpp PRIVATE LIBSCRATCHCPP_LIBRARY)
target_compile_definitions(scratchcpp PRIVATE LIBSCRATCHCPP_VERSION="${PROJECT_VERSION}")
Expand Down
6 changes: 0 additions & 6 deletions include/scratchcpp/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ namespace libscratchcpp

class IEngine;
class Target;
#ifdef USE_LLVM
class CompilerValue;
#endif
class Input;
class Field;
class Comment;
Expand All @@ -28,11 +26,7 @@ class LIBSCRATCHCPP_EXPORT Block : public Entity
Block(const std::string &id, const std::string &opcode);
Block(const Block &) = delete;

#ifdef USE_LLVM
CompilerValue *compile(Compiler *compiler);
#else
void compile(Compiler *compiler);
#endif

const std::string &opcode() const;

Expand Down
164 changes: 112 additions & 52 deletions include/scratchcpp/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,89 +2,149 @@

#pragma once

#include <vector>
#include <memory>
#include <unordered_set>
#include <vector>

#include "global.h"
#include "spimpl.h"
#include "virtualmachine.h"
#include "value.h"

namespace libscratchcpp
{

class CompilerContext;
class IEngine;
class Block;
class Input;
class InputValue;
class Field;
class Target;
class ExecutableCode;
class CompilerValue;
class CompilerConstant;
class CompilerLocalVariable;
class Variable;
class List;
class Input;
class Field;
class BlockPrototype;
class Entity;
class CompilerPrivate;

/*! \brief The Compiler class provides an API for compiling scripts of targets to bytecode. */
/*! \brief The Compiler class provides API for compiling Scratch scripts. */
class LIBSCRATCHCPP_EXPORT Compiler
{
public:
enum class SubstackType
enum class StaticType
{
Loop,
IfStatement
Void,
Number,
Bool,
String,
Unknown
};

Compiler(IEngine *engine, Target *target = nullptr);
Compiler(const Compiler &) = delete;

void init();
void compile(std::shared_ptr<Block> topLevelBlock);
void end();
using ArgTypes = std::vector<StaticType>;
using Args = std::vector<CompilerValue *>;

const std::vector<unsigned int> &bytecode() const;
const std::vector<unsigned int> &hatPredicateBytecode() const;
Compiler(CompilerContext *ctx);
Compiler(IEngine *engine, Target *target);
Compiler(const Compiler &) = delete;

IEngine *engine() const;
Target *target() const;

const std::vector<InputValue *> &constInputValues() const;
std::vector<Value> constValues() const;

const std::vector<Variable *> &variables() const;
std::vector<Value *> variablePtrs() const;

const std::vector<List *> &lists() const;

void addInstruction(vm::Opcode opcode, const std::initializer_list<unsigned int> &args = {});
void addInput(Input *input);
void addInput(int id);
void addConstValue(const Value &value);
void addFunctionCall(BlockFunc f);
void addProcedureArg(const std::string &procCode, const std::string &argName);
void moveToSubstack(std::shared_ptr<Block> substack1, std::shared_ptr<Block> substack2, SubstackType type);
void moveToSubstack(std::shared_ptr<Block> substack, SubstackType type);
std::shared_ptr<Block> block() const;

std::shared_ptr<ExecutableCode> compile(std::shared_ptr<Block> startBlock);
void preoptimize();

CompilerValue *addFunctionCall(const std::string &functionName, StaticType returnType = StaticType::Void, const ArgTypes &argTypes = {}, const Args &args = {});
CompilerValue *addTargetFunctionCall(const std::string &functionName, StaticType returnType = StaticType::Void, const ArgTypes &argTypes = {}, const Args &args = {});
CompilerValue *addFunctionCallWithCtx(const std::string &functionName, StaticType returnType = StaticType::Void, const ArgTypes &argTypes = {}, const Args &args = {});
CompilerConstant *addConstValue(const Value &value);
CompilerValue *addLoopIndex();
CompilerValue *addLocalVariableValue(CompilerLocalVariable *variable);
CompilerValue *addVariableValue(Variable *variable);
CompilerValue *addListContents(List *list);
CompilerValue *addListItem(List *list, CompilerValue *index);
CompilerValue *addListItemIndex(List *list, CompilerValue *item);
CompilerValue *addListContains(List *list, CompilerValue *item);
CompilerValue *addListSize(List *list);
CompilerValue *addProcedureArgument(const std::string &name);

CompilerValue *addInput(const std::string &name);
CompilerValue *addInput(Input *input);

CompilerValue *createAdd(CompilerValue *operand1, CompilerValue *operand2);
CompilerValue *createSub(CompilerValue *operand1, CompilerValue *operand2);
CompilerValue *createMul(CompilerValue *operand1, CompilerValue *operand2);
CompilerValue *createDiv(CompilerValue *operand1, CompilerValue *operand2);

CompilerValue *createRandom(CompilerValue *from, CompilerValue *to);
CompilerValue *createRandomInt(CompilerValue *from, CompilerValue *to);

CompilerValue *createCmpEQ(CompilerValue *operand1, CompilerValue *operand2);
CompilerValue *createCmpGT(CompilerValue *operand1, CompilerValue *operand2);
CompilerValue *createCmpLT(CompilerValue *operand1, CompilerValue *operand2);

CompilerValue *createStrCmpEQ(CompilerValue *string1, CompilerValue *string2, bool caseSensitive = false);

CompilerValue *createAnd(CompilerValue *operand1, CompilerValue *operand2);
CompilerValue *createOr(CompilerValue *operand1, CompilerValue *operand2);
CompilerValue *createNot(CompilerValue *operand);

CompilerValue *createMod(CompilerValue *num1, CompilerValue *num2);
CompilerValue *createRound(CompilerValue *num);
CompilerValue *createAbs(CompilerValue *num);
CompilerValue *createFloor(CompilerValue *num);
CompilerValue *createCeil(CompilerValue *num);
CompilerValue *createSqrt(CompilerValue *num);
CompilerValue *createSin(CompilerValue *num);
CompilerValue *createCos(CompilerValue *num);
CompilerValue *createTan(CompilerValue *num);
CompilerValue *createAsin(CompilerValue *num);
CompilerValue *createAcos(CompilerValue *num);
CompilerValue *createAtan(CompilerValue *num);
CompilerValue *createLn(CompilerValue *num);
CompilerValue *createLog10(CompilerValue *num);
CompilerValue *createExp(CompilerValue *num);
CompilerValue *createExp10(CompilerValue *num);

CompilerValue *createSelect(CompilerValue *cond, CompilerValue *trueValue, CompilerValue *falseValue, Compiler::StaticType valueType);

CompilerLocalVariable *createLocalVariable(Compiler::StaticType type);
void createLocalVariableWrite(CompilerLocalVariable *variable, CompilerValue *value);

void createVariableWrite(Variable *variable, CompilerValue *value);

void createListClear(List *list);
void createListRemove(List *list, CompilerValue *index);
void createListAppend(List *list, CompilerValue *item);
void createListInsert(List *list, CompilerValue *index, CompilerValue *item);
void createListReplace(List *list, CompilerValue *index, CompilerValue *item);

void beginIfStatement(CompilerValue *cond);
void beginElseBranch();
void endIf();

void beginWhileLoop(CompilerValue *cond);
void beginRepeatUntilLoop(CompilerValue *cond);
void beginLoopCondition();
void endLoop();

void moveToIf(CompilerValue *cond, std::shared_ptr<Block> substack);
void moveToIfElse(CompilerValue *cond, std::shared_ptr<Block> substack1, std::shared_ptr<Block> substack2);
void moveToRepeatLoop(CompilerValue *count, std::shared_ptr<Block> substack);
void moveToWhileLoop(CompilerValue *cond, std::shared_ptr<Block> substack);
void moveToRepeatUntilLoop(CompilerValue *cond, std::shared_ptr<Block> substack);
void warp();

Input *input(int id) const;
Field *field(int id) const;
std::shared_ptr<Block> inputBlock(int id) const;
unsigned int variableIndex(std::shared_ptr<Entity> varEntity);
unsigned int listIndex(std::shared_ptr<Entity> listEntity);
unsigned int constIndex(InputValue *value);
unsigned int procedureIndex(const std::string &proc);
long procedureArgIndex(const std::string &procCode, const std::string &argName);

const std::vector<std::string> &procedures() const;
void createYield();
void createStop();

const std::shared_ptr<Block> &block() const;
void setBlock(std::shared_ptr<Block> block);
void createProcedureCall(BlockPrototype *prototype, const Compiler::Args &args);

BlockPrototype *procedurePrototype() const;
void setProcedurePrototype(BlockPrototype *prototype);
Input *input(const std::string &name) const;
Field *field(const std::string &name) const;

const std::unordered_set<std::string> &unsupportedBlocks() const;

static std::shared_ptr<CompilerContext> createContext(IEngine *engine, Target *target);

private:
spimpl::unique_impl_ptr<CompilerPrivate> impl;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

#pragma once

#include "../global.h"
#include "../spimpl.h"
#include "global.h"
#include "spimpl.h"

namespace libscratchcpp
{
Expand Down
Loading
Loading