Skip to content

Commit

Permalink
Extend IRGenerator
Browse files Browse the repository at this point in the history
  • Loading branch information
marcauberer committed Dec 18, 2022
1 parent bc4d12c commit fd63e9e
Show file tree
Hide file tree
Showing 44 changed files with 3,921 additions and 2,222 deletions.
2 changes: 1 addition & 1 deletion .run/spice.run.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="spice" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="run -d -j 1 -O2 ../../media/test-project/os-test.spice" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="Spice" TARGET_NAME="spice" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="Spice" RUN_TARGET_NAME="spice">
<configuration default="false" name="spice" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="run -d -j 1 -O2 -ir ../../media/test-project/os-test.spice" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="Spice" TARGET_NAME="spice" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="Spice" RUN_TARGET_NAME="spice">
<envs>
<env name="CONSOLE_WIDTH" value="300" />
<env name="RUN_TESTS" value="OFF" />
Expand Down
104 changes: 104 additions & 0 deletions docs/docs/language/object-orientation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
title: Object-oriented programming
---

Spice supports object-oriented programming in the form of composition. That means that types can be composed via
structs, interfaces and methods.

## Example scenario

You need to model three different kinds of objects: humans, cars and parrots. Therefore, you create three structs with
the respective names:

```spice
type Human struct {
string firstName
string lastName
unsigned int age
}
type Car struct {
string brand
string model
unsigned int seats
}
type Parrot struct {
string name
unsigned int age
}
```

Now, as you have a speaking parrot, you want to give the parrot and the human the ability to speak. In addition to that,
all three objects can make sounds. The recommended way of doing this, is to use interfaces like this:

```spice
type Speak interface {
p sayHello(string);
}
type MakeSound interface {
p makeSound();
}
type Human struct : MakeSound, Speak {
string firstName
string lastName
unsigned int age
}
p Human.makeSound() {
// Sigh ...
}
p Human.sayHello() {
// Hi!
}
type Car struct : MakeSound {
string brand
string model
unsigned int seats
}
p Car.makeSound() {
// Wroom, wroom
}
type Parrot struct : MakeSound, Speak {
string name
unsigned int age
}
p Parrot.makeSound() {
// Sqawk!
}
p Parrot.sayHello() {
// Hello, squawk!
}
```

As all living beings, parrots and humans have an age. So you might want to extract the `unsigned int age`, that exists
in both structs to a separate struct called `LivingBeing`.

```spice
// ...
type LivingBeing struct {
unsigned int age
}
type Human struct : MakeSound, Speak {
LivingBeing livingBeing
string firstName
string lastName
}
type Parrot struct : MakeSound, Speak {
LivingBeing livingBeing
string name
}
// ...
```
9 changes: 6 additions & 3 deletions media/test-project/os-test.spice
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//import "std/type/int" as unused;
f<int> test(int i, int j = 12, string t = "Test") {
printf("Test: %d, %s", j, t);
return i;
}

f<int> main() {
unsigned int t = 12u;
printf("%d", t);
test(1);
test(1, 3);
}
4 changes: 2 additions & 2 deletions src-bootstrap/ast/AstNodes.spice
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public type AstNode struct : Visitable {
vec::Vector<AstNode*> children
const cl::CodeLoc codeLoc
string errorMessage
unsigned long symbolTypeIndex
unsigned long manIdx
vec::Vector<symbolType::SymbolType> symbolTypes
CompileTimeValue compileTimeValue
string compileTimeStringValue
Expand All @@ -43,7 +43,7 @@ public type AstNode struct : Visitable {
p AstNode.ctor(AstNode *parent, cl::CodeLoc codeLoc) {
this.parent = parent;
this.codeLoc = codeLoc;
this.symbolTypeIndex = longTy::MAX_VALUE;
this.manIdx = longTy::MAX_VALUE;
hasDirectCompileTimeValue = false;
}

Expand Down
4 changes: 2 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ set(SOURCES
irgenerator/GenValues.cpp
irgenerator/StdFunctionManager.cpp
irgenerator/StdFunctionManager.h
irgenerator/OpRuleConversionsManager.cpp
irgenerator/OpRuleConversionsManager.h
irgenerator/OpRuleConversionManager.cpp
irgenerator/OpRuleConversionManager.h
irgenerator/DebugInfoGenerator.cpp
irgenerator/DebugInfoGenerator.h
# IR optimizer
Expand Down
7 changes: 5 additions & 2 deletions src/ast/ASTBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,10 @@ std::any ASTBuilder::visitGlobalVarDef(SpiceParser::GlobalVarDefContext *ctx) {
currentNode = globalVarDefNode->createChild<SpecifierLstNode>(CodeLoc(rule->start, filePath));
else if (rule = dynamic_cast<SpiceParser::DataTypeContext *>(subTree); rule != nullptr) // DataType
currentNode = globalVarDefNode->createChild<DataTypeNode>(CodeLoc(rule->start, filePath));
else if (rule = dynamic_cast<SpiceParser::ConstantContext *>(subTree); rule != nullptr) // Constant
else if (rule = dynamic_cast<SpiceParser::ConstantContext *>(subTree); rule != nullptr) { // Constant
currentNode = globalVarDefNode->createChild<ConstantNode>(CodeLoc(rule->start, filePath));
else
globalVarDefNode->hasAssigment = true;
} else
assert(dynamic_cast<antlr4::tree::TerminalNode *>(subTree)); // Fail if we did not get a terminal

if (currentNode != globalVarDefNode) {
Expand Down Expand Up @@ -572,6 +573,8 @@ std::any ASTBuilder::visitStmtLst(SpiceParser::StmtLstContext *ctx) {
currentNode = stmtLstNode->createChild<ForeachLoopNode>(CodeLoc(rule->start, filePath));
else if (rule = dynamic_cast<SpiceParser::WhileLoopContext *>(subTree); rule != nullptr) // WhileLoop
currentNode = stmtLstNode->createChild<WhileLoopNode>(CodeLoc(rule->start, filePath));
else if (rule = dynamic_cast<SpiceParser::DoWhileLoopContext *>(subTree); rule != nullptr) // DoWhileLoop
currentNode = stmtLstNode->createChild<DoWhileLoopNode>(CodeLoc(rule->start, filePath));
else if (rule = dynamic_cast<SpiceParser::IfStmtContext *>(subTree); rule != nullptr) // IfStmt
currentNode = stmtLstNode->createChild<IfStmtNode>(CodeLoc(rule->start, filePath));
else if (rule = dynamic_cast<SpiceParser::AssertStmtContext *>(subTree); rule != nullptr) // AssertStmt
Expand Down

0 comments on commit fd63e9e

Please sign in to comment.