forked from solstice/solstice
Compare commits
83 Commits
5196f73e16
...
rewrite
| Author | SHA1 | Date | |
|---|---|---|---|
| 7c0490668e | |||
| e5da1d255b | |||
| c0c35e4d17 | |||
| f67c045845 | |||
| 98c8775208 | |||
| f384e19c06 | |||
| d24462f844 | |||
| 4351821d30 | |||
| 78f974e189 | |||
| 1dedb30a87 | |||
| 2e7b5b7480 | |||
| 1cf995f7ac | |||
| 605d0a87b1 | |||
| 16569d7355 | |||
| fd08b7cdb7 | |||
| 5841a7a999 | |||
| a2fc138ba1 | |||
| 9b55b509f5 | |||
| f694f50d70 | |||
| 5b61a11f00 | |||
| 00d6ed83fb | |||
| 6988f314b0 | |||
| 70dc5eb5a0 | |||
| 1e3bd6c601 | |||
| f66464a7cc | |||
| 631b587d07 | |||
| 445ba032f5 | |||
| 41a2fa53c6 | |||
| 00ef8a7d56 | |||
| f1eee4f6a8 | |||
| cfca3c1d7a | |||
| 40e0aec0d4 | |||
| 38473f0e01 | |||
| 139be30e2d | |||
| d576c7cdfc | |||
| 2e4dbce100 | |||
| ea6bf5925b | |||
| 142268c016 | |||
| 1c6b145d35 | |||
| 6002bd922b | |||
| 4b86fee7b5 | |||
| d12036fe70 | |||
| 59e273b26e | |||
| e285b2c59f | |||
| e3abe07f4b | |||
| 010d155f5d | |||
| 44785185f7 | |||
| c82f81f668 | |||
| 9397f410da | |||
| 6d5d29f05b | |||
| 48c130351a | |||
| 6bc483b1db | |||
| c5b67bff72 | |||
| ca8db171d9 | |||
| c266728ff0 | |||
| b46a66cea7 | |||
| 337b88c148 | |||
| d8812fa14e | |||
| 24ea348858 | |||
| 9a311c3cb8 | |||
| aa5ef0e664 | |||
| 7ff306b9e8 | |||
| ac7f22e1bc | |||
| 5ec2f86b70 | |||
| 7dd2b10603 | |||
| 7351604571 | |||
| 43310c70bf | |||
| 957e0fd95a | |||
| 525b2bc733 | |||
| d2f295f46a | |||
| 869f71466e | |||
| a3a9553189 | |||
| 3c66df5be0 | |||
| ce058c8f9c | |||
| 2aff15a317 | |||
| 72ec9c1fb6 | |||
| c04e631180 | |||
| 16a406b52f | |||
| 0488067ef2 | |||
| a8e5f6a0f1 | |||
| e8bf7b70f7 | |||
| b5c8b1b7ec | |||
| 99bc0dbdc2 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1 +1,3 @@
|
|||||||
hg
|
solstice
|
||||||
|
build
|
||||||
|
.*_solsbuild
|
||||||
|
|||||||
5
.project.fish
Normal file
5
.project.fish
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# source .project.fish
|
||||||
|
|
||||||
|
alias run "make && ./solstice"
|
||||||
|
alias clean "make clean"
|
||||||
|
alias cleanrun "make clean && make && ./solstice"
|
||||||
42
README.md
42
README.md
@@ -1,49 +1,21 @@
|
|||||||
# High Ground
|

|
||||||
|
|
||||||
High Ground is a programming language based on Ground.
|
# Solstice
|
||||||
|
|
||||||
It is the reference language designed to teach you how to build your own Ground-based language.
|
Solstice is a programming language based on Ground.
|
||||||
|
|
||||||
## Compiling
|
## Compiling
|
||||||
|
|
||||||
First, ensure CGround is installed on your system with `sudo make install`. Then, compile with
|
First, ensure CGround is installed on your system with `sudo make install`. Then, compile with
|
||||||
|
|
||||||
```
|
```
|
||||||
g++ src/main.cpp -o hg -lgroundvm
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
High Ground files use the `.hg` extension. Run files as you would with any other interpreted language.
|
Solstice files use the `.sols` extension. Run files as you would with any other interpreted language.
|
||||||
|
|
||||||
## Using High Ground
|
## Docs
|
||||||
|
|
||||||
### Types
|
Docs are avaliable at https://sols.dev/docs/
|
||||||
|
|
||||||
* `int`: Ground int (64 bit integer) eg 3, 7, 31432
|
|
||||||
* `double`: Ground double (Double precision floating point) eg 3.141, 2.7
|
|
||||||
* `string`: Ground string (char*) eg "Hello, World"
|
|
||||||
* `char`: Ground char (char) eg 'a'
|
|
||||||
* `bool`: Ground bool (either true or false)
|
|
||||||
|
|
||||||
### Printing
|
|
||||||
|
|
||||||
Prefix an expression with `puts` to print it to the console.
|
|
||||||
|
|
||||||
```
|
|
||||||
puts "Hello, world!"
|
|
||||||
puts 3.141
|
|
||||||
puts 7
|
|
||||||
puts 'a'
|
|
||||||
puts true
|
|
||||||
```
|
|
||||||
|
|
||||||
### Math
|
|
||||||
|
|
||||||
Add numbers with `+` (more operations coming soon)
|
|
||||||
|
|
||||||
```
|
|
||||||
puts 1 + 1
|
|
||||||
puts 3.14 + 2.7
|
|
||||||
puts 532 + 314 + 89432
|
|
||||||
```
|
|
||||||
14
chookspace/index.html
Normal file
14
chookspace/index.html
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Redirecting to sols.dev</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Redirecting to sols.dev, if that doesn't work <a href="https://sols.dev">click here</a>.</p>
|
||||||
|
<script>
|
||||||
|
window.location.href = "https://sols.dev";
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
15
libs/conversions.sols
Normal file
15
libs/conversions.sols
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
def stringToInt(string in) int {
|
||||||
|
result = 0
|
||||||
|
ground {
|
||||||
|
stoi $in &result
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
def intToString(int in) string {
|
||||||
|
result = ""
|
||||||
|
ground {
|
||||||
|
tostring $in &result
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
6
libs/file.sols
Normal file
6
libs/file.sols
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
def file_Read(string file) string {}
|
||||||
|
def file_Write(string file, string content) bool {}
|
||||||
|
|
||||||
|
ground {
|
||||||
|
extern "fileio"
|
||||||
|
}
|
||||||
23
libs/io.sols
Normal file
23
libs/io.sols
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
def input(string msg) string {
|
||||||
|
retval = ""
|
||||||
|
ground {
|
||||||
|
print $msg
|
||||||
|
input &retval
|
||||||
|
}
|
||||||
|
return retval
|
||||||
|
}
|
||||||
|
|
||||||
|
def print(string msg) string {
|
||||||
|
ground {
|
||||||
|
print $msg
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
def println(string msg) string {
|
||||||
|
ground {
|
||||||
|
println $msg
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
12
libs/request.sols
Normal file
12
libs/request.sols
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
def request_Get(string url) string {}
|
||||||
|
def request_Post(string url, string data) string {}
|
||||||
|
def ws_Connect(string url) int {}
|
||||||
|
def ws_Send(int connId, string data) int {}
|
||||||
|
def ws_SendBinary(int connId, string data) int {}
|
||||||
|
def ws_Receive(int connId) string {}
|
||||||
|
def ws_ReceiveTimeout(int connId, int timeout) string {}
|
||||||
|
def ws_Close(int connId) bool {}
|
||||||
|
|
||||||
|
ground {
|
||||||
|
extern "request"
|
||||||
|
}
|
||||||
43
libs/unistd.sols
Normal file
43
libs/unistd.sols
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
def unistd_Crypt(string key, string value) string {}
|
||||||
|
def unistd_GetHostId() string {}
|
||||||
|
def unistd_SetHotId(int hostid) int {}
|
||||||
|
def unistd_GetHostname() string {}
|
||||||
|
def unistd_SetHostname(string name) int {}
|
||||||
|
|
||||||
|
def unistd_Alarm(int seconds) int {}
|
||||||
|
def unistd_Pause() int {}
|
||||||
|
|
||||||
|
unistd_F_OK = 0
|
||||||
|
unistd_R_OK = 0
|
||||||
|
unistd_W_OK = 0
|
||||||
|
unistd_X_OK = 0
|
||||||
|
|
||||||
|
def unistd_Access(string path, int mode) int {}
|
||||||
|
def unistd_Chdir(string path) int {}
|
||||||
|
def unistd_Chown(string path, int owner, int group) int {}
|
||||||
|
def unistd_Link(string oldpath, string newpath) int {}
|
||||||
|
def unistd_Rmdir(string path) int {}
|
||||||
|
def unistd_Symlink(string target, string linkpath) int {}
|
||||||
|
|
||||||
|
def unistd_Exit(int status) int {}
|
||||||
|
def unistd_Fork() int {}
|
||||||
|
def unistd_GetPid() int {}
|
||||||
|
def unistd_GetPPid() int {}
|
||||||
|
def unistd_GetSid(int pid) int {}
|
||||||
|
def unistd_Nice(int inc) int {}
|
||||||
|
def unistd_SetSid() int {}
|
||||||
|
def unistd_Sleep(int seconds) int {}
|
||||||
|
|
||||||
|
def unistd_GetGid() int {}
|
||||||
|
def unistd_GetEGid() int {}
|
||||||
|
def unistd_GetUid() int {}
|
||||||
|
def unistd_GetEUid() int {}
|
||||||
|
def unistd_GetLogin() string {}
|
||||||
|
def unistd_SetEUid(int euid) int {}
|
||||||
|
def unistd_SetEGid(int egid) int {}
|
||||||
|
def unistd_SetREUid(int ruid, int euid) int {}
|
||||||
|
def unistd_SetREGid(int rgid, int egid) int {}
|
||||||
|
|
||||||
|
ground {
|
||||||
|
extern "unistd"
|
||||||
|
}
|
||||||
BIN
logo/solstice.png
Normal file
BIN
logo/solstice.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
78
logo/solstice.svg
Normal file
78
logo/solstice.svg
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="210mm"
|
||||||
|
height="297mm"
|
||||||
|
viewBox="0 0 210 297"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||||
|
sodipodi:docname="solstice.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:zoom="1.8101934"
|
||||||
|
inkscape:cx="341.39999"
|
||||||
|
inkscape:cy="633.35776"
|
||||||
|
inkscape:window-width="1908"
|
||||||
|
inkscape:window-height="1028"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1" />
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient8"
|
||||||
|
inkscape:collect="always">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#64ffe1;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop8" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#a3b9f5;stop-opacity:1;"
|
||||||
|
offset="0.5"
|
||||||
|
id="stop10" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#d1b8fb;stop-opacity:1;"
|
||||||
|
offset="0.75"
|
||||||
|
id="stop11" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#f3cdff;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop9" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient8"
|
||||||
|
id="linearGradient9"
|
||||||
|
x1="-42.253399"
|
||||||
|
y1="135.74071"
|
||||||
|
x2="-41.225731"
|
||||||
|
y2="239.96782"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.73239966,-0.77274564,0.76516532,0.73965537,-4.0932457,-8.6853091)" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
id="path1"
|
||||||
|
style="fill:url(#linearGradient9);fill-opacity:1;stroke:#ffffff;stroke-width:0.281629;stroke-opacity:0"
|
||||||
|
d="m 100.38267,124.7767 a 31.775753,32.090549 0 0 0 -22.257004,9.893 31.775753,32.090549 0 0 0 0.979215,45.36846 l -0.0038,0.004 45.917939,44.38672 43.95132,-46.37229 -45.91795,-44.38673 -0.004,0.004 a 31.775753,32.090549 0 0 0 -22.66587,-8.8969 z" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.5 KiB |
BIN
src/lexer/.DS_Store
vendored
Normal file
BIN
src/lexer/.DS_Store
vendored
Normal file
Binary file not shown.
97
src/lexer/lexer.sols
Normal file
97
src/lexer/lexer.sols
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
use collections
|
||||||
|
use string
|
||||||
|
|
||||||
|
//
|
||||||
|
// Token type enum.
|
||||||
|
//
|
||||||
|
// Each token can be one of these types.
|
||||||
|
//
|
||||||
|
enum SolsToken {
|
||||||
|
Identifier, Literal, Type,
|
||||||
|
|
||||||
|
Dot, OpenCurly, CloseCurly, OpenParen, CloseParen, Comma,
|
||||||
|
|
||||||
|
OpAdd, OpSub, OpMul, OpDiv, OpAddTo, OpSubTo, OpMulTo, OpDivTo, OpIncrement, OpDecrement, OpSet,
|
||||||
|
OpGreater, OpLesser, OpEqual, OpInequal, OpEqGreater, OpEqLesser,
|
||||||
|
|
||||||
|
KwDef, KwLambda, KwReturn, KwUse, KwStruct, KwEnum, KwConstructor,
|
||||||
|
KwDestructor, KwDuplicator, KwPrivate, KwProtected, KwPuts, KwIf,
|
||||||
|
KwWhile, KwNew, KwGround,
|
||||||
|
|
||||||
|
LineEnd,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Token type map.
|
||||||
|
//
|
||||||
|
// If a token matches one of the strings in this hashmap,
|
||||||
|
// its type gets set to the token type for that string.
|
||||||
|
//
|
||||||
|
KEYWORDS = Hashmap()
|
||||||
|
KEYWORDS.set("puts", SolsToken.KwPuts)
|
||||||
|
KEYWORDS.set("if", SolsToken.KwIf)
|
||||||
|
KEYWORDS.set("while", SolsToken.KwWhile)
|
||||||
|
KEYWORDS.set("def", SolsToken.KwDef)
|
||||||
|
KEYWORDS.set("lambda", SolsToken.KwLambda)
|
||||||
|
KEYWORDS.set("return", SolsToken.KwReturn)
|
||||||
|
KEYWORDS.set("use", SolsToken.KwUse)
|
||||||
|
KEYWORDS.set("struct", SolsToken.KwStruct)
|
||||||
|
KEYWORDS.set("enum", SolsToken.KwEnum)
|
||||||
|
KEYWORDS.set("constructor", SolsToken.KwConstructor)
|
||||||
|
KEYWORDS.set("destructor", SolsToken.KwDestructor)
|
||||||
|
KEYWORDS.set("duplicator", SolsToken.KwDuplicator)
|
||||||
|
KEYWORDS.set("private", SolsToken.KwPrivate)
|
||||||
|
KEYWORDS.set("protected", SolsToken.KwProtected)
|
||||||
|
KEYWORDS.set("ground", SolsToken.KwGround)
|
||||||
|
KEYWORDS.set("new", SolsToken.KwNew)
|
||||||
|
KEYWORDS.set("{", SolsToken.OpenCurly)
|
||||||
|
KEYWORDS.set("}", SolsToken.CloseCurly)
|
||||||
|
KEYWORDS.set("(", SolsToken.OpenParen)
|
||||||
|
KEYWORDS.set(")", SolsToken.CloseParen)
|
||||||
|
KEYWORDS.set("+", SolsToken.OpAdd)
|
||||||
|
KEYWORDS.set("-", SolsToken.OpSub)
|
||||||
|
KEYWORDS.set("*", SolsToken.OpMul)
|
||||||
|
KEYWORDS.set("/", SolsToken.OpDiv)
|
||||||
|
KEYWORDS.set("=", SolsToken.OpSet)
|
||||||
|
KEYWORDS.set("+=", SolsToken.OpAddTo)
|
||||||
|
KEYWORDS.set("-=", SolsToken.OpSubTo)
|
||||||
|
KEYWORDS.set("*=", SolsToken.OpMulTo)
|
||||||
|
KEYWORDS.set("/=", SolsToken.OpDivTo)
|
||||||
|
KEYWORDS.set("++", SolsToken.OpIncrement)
|
||||||
|
KEYWORDS.set("--", SolsToken.OpDecrement)
|
||||||
|
KEYWORDS.set("==", SolsToken.OpEqual)
|
||||||
|
KEYWORDS.set("!=", SolsToken.OpInequal)
|
||||||
|
KEYWORDS.set(">", SolsToken.OpGreater)
|
||||||
|
KEYWORDS.set("<", SolsToken.OpLesser)
|
||||||
|
KEYWORDS.set(">=", SolsToken.OpEqGreater)
|
||||||
|
KEYWORDS.set("<=", SolsToken.OpEqLesser)
|
||||||
|
KEYWORDS.set("\n", SolsToken.LineEnd)
|
||||||
|
KEYWORDS.set(";", SolsToken.LineEnd)
|
||||||
|
KEYWORDS.set(",", SolsToken.Comma)
|
||||||
|
|
||||||
|
struct SolsLexer {
|
||||||
|
sourceCode = "x = 123"
|
||||||
|
current = 0
|
||||||
|
|
||||||
|
private def getTokenType(string input) SolsToken {
|
||||||
|
return KEYWORDS.get(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
def lex() {
|
||||||
|
inString = false
|
||||||
|
|
||||||
|
lineNum = 1
|
||||||
|
lineStart = 0
|
||||||
|
currentLine = ""
|
||||||
|
|
||||||
|
while lineStart < string_Length() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
lexer = new SolsLexer
|
||||||
|
puts lexer.getTokenType("if")
|
||||||
563
src/main.cpp
563
src/main.cpp
@@ -1,563 +0,0 @@
|
|||||||
#include <cctype>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <groundvm.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <optional>
|
|
||||||
#include <variant>
|
|
||||||
|
|
||||||
#define parseOneToken(token) Parser({token.value()}).parse().children[0]
|
|
||||||
|
|
||||||
namespace HighGround {
|
|
||||||
|
|
||||||
int tmpIdIterator = 0;
|
|
||||||
|
|
||||||
namespace Parser {
|
|
||||||
|
|
||||||
enum class HGNodeType {
|
|
||||||
Add, Subtract, Equal, Set, While, If, Value, Identifier, None, Root, CodeBlock, CodeBlockStart, CodeBlockEnd, Puts
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class HGDataType {
|
|
||||||
Int, String, Double, Bool, Char, None
|
|
||||||
};
|
|
||||||
|
|
||||||
class HGNode;
|
|
||||||
|
|
||||||
class HGGroundCodeBlock {
|
|
||||||
public:
|
|
||||||
std::vector<GroundInstruction> code;
|
|
||||||
HGGroundCodeBlock() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
class HGData {
|
|
||||||
typedef std::variant<int64_t, std::string, double, bool, char> varData;
|
|
||||||
varData data;
|
|
||||||
public:
|
|
||||||
HGDataType type = HGDataType::Int;
|
|
||||||
HGData() = default;
|
|
||||||
HGData(int64_t in) : data(in), type(HGDataType::Int) {}
|
|
||||||
HGData(double in) : data(in), type(HGDataType::Double) {}
|
|
||||||
HGData(std::string in) : data(in), type(HGDataType::String) {}
|
|
||||||
HGData(char in) : data(in), type(HGDataType::Char) {}
|
|
||||||
HGData(bool in) : data(in), type(HGDataType::Bool) {}
|
|
||||||
std::optional<int64_t> getInt() {
|
|
||||||
if (type == HGDataType::Int) {
|
|
||||||
return std::get<int64_t>(data);
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::optional<double> getDouble() {
|
|
||||||
if (type == HGDataType::Double) {
|
|
||||||
return std::get<double>(data);
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::optional<std::string> getString() {
|
|
||||||
if (type == HGDataType::String) {
|
|
||||||
return std::get<std::string>(data);
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::optional<char> getChar() {
|
|
||||||
if (type == HGDataType::Char) {
|
|
||||||
return std::get<char>(data);
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::optional<bool> getBool() {
|
|
||||||
if (type == HGDataType::Bool) {
|
|
||||||
return std::get<bool>(data);
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class HGNode {
|
|
||||||
HGNodeType nodeType = HGNodeType::None;
|
|
||||||
HGData data;
|
|
||||||
public:
|
|
||||||
std::vector<HGNode> children;
|
|
||||||
std::string outputId;
|
|
||||||
HGNode(HGNodeType nodeType) : nodeType(nodeType) {}
|
|
||||||
HGNode(HGNodeType nodeType, HGData data) : nodeType(nodeType), data(data) {}
|
|
||||||
HGNode() = default;
|
|
||||||
void addNode(HGNode in) {
|
|
||||||
children.push_back(in);
|
|
||||||
}
|
|
||||||
void setValue(HGData in) {
|
|
||||||
data = in;
|
|
||||||
}
|
|
||||||
const std::vector<HGGroundCodeBlock> generateCode() {
|
|
||||||
std::vector<HGGroundCodeBlock> code;
|
|
||||||
for (auto& child : children) {
|
|
||||||
auto childCode = child.generateCode();
|
|
||||||
code.insert(code.end(), childCode.begin(), childCode.end());
|
|
||||||
}
|
|
||||||
switch (nodeType) {
|
|
||||||
case HGNodeType::Value: {
|
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
|
||||||
HGGroundCodeBlock codeBlock;
|
|
||||||
GroundInstruction gi = groundCreateInstruction(SET);
|
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data()));
|
|
||||||
switch (data.type) {
|
|
||||||
case HGDataType::Int: {
|
|
||||||
auto dataopt = data.getInt();
|
|
||||||
if (dataopt) {
|
|
||||||
groundAddValueToInstruction(&gi, groundCreateValue(INT, dataopt.value()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HGDataType::Double: {
|
|
||||||
auto dataopt = data.getDouble();
|
|
||||||
if (dataopt) {
|
|
||||||
groundAddValueToInstruction(&gi, groundCreateValue(DOUBLE, dataopt.value()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HGDataType::String: {
|
|
||||||
auto dataopt = data.getString();
|
|
||||||
if (dataopt) {
|
|
||||||
groundAddValueToInstruction(&gi, groundCreateValue(STRING, dataopt.value().c_str()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HGDataType::Char: {
|
|
||||||
auto dataopt = data.getChar();
|
|
||||||
if (dataopt) {
|
|
||||||
groundAddValueToInstruction(&gi, groundCreateValue(CHAR, dataopt.value()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HGDataType::Bool: {
|
|
||||||
auto dataopt = data.getBool();
|
|
||||||
if (dataopt) {
|
|
||||||
groundAddValueToInstruction(&gi, groundCreateValue(BOOL, dataopt.value()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
codeBlock.code.push_back(gi);
|
|
||||||
code.push_back(codeBlock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HGNodeType::Add: {
|
|
||||||
HGGroundCodeBlock codeBlock;
|
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
|
||||||
GroundInstruction gi = groundCreateInstruction(ADD);
|
|
||||||
if (children.size() < 2) {
|
|
||||||
std::cout << "Need more stuff to add\n";
|
|
||||||
}
|
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data()));
|
|
||||||
codeBlock.code.push_back(gi);
|
|
||||||
code.push_back(codeBlock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HGNodeType::Puts: {
|
|
||||||
HGGroundCodeBlock codeBlock;
|
|
||||||
GroundInstruction gi = groundCreateInstruction(PRINTLN);
|
|
||||||
if (children.size() < 1) {
|
|
||||||
std::cout << "Need more stuff to puts\n";
|
|
||||||
}
|
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
|
||||||
codeBlock.code.push_back(gi);
|
|
||||||
code.push_back(codeBlock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {}
|
|
||||||
}
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class Parser {
|
|
||||||
std::vector<std::string> tokensToParse;
|
|
||||||
size_t current;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
std::optional<std::string> peek(int ahead = 1) {
|
|
||||||
if (current + ahead < size) {
|
|
||||||
return tokensToParse[current + ahead];
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<std::string> consume() {
|
|
||||||
if (current < size) {
|
|
||||||
return tokensToParse[current++];
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isInt(std::string in) {
|
|
||||||
for (const char& c : in) {
|
|
||||||
if (!std::isdigit(c)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool isDouble(std::string in) {
|
|
||||||
bool foundDot = false;
|
|
||||||
for (const char& c : in) {
|
|
||||||
if (!std::isdigit(c)) {
|
|
||||||
if (!foundDot && c == '.') {
|
|
||||||
foundDot = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool isString(std::string in) {
|
|
||||||
if (in.size() > 1 && in[0] == '"' && in.back() == '"') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool isChar(std::string in) {
|
|
||||||
if (in.size() == 3 && in[0] == '\'' && in.back() == '\'') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool isBool(std::string in) {
|
|
||||||
if (in == "true" || in == "false") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGDataType getDataType(std::string in) {
|
|
||||||
if (isInt(in)) {
|
|
||||||
return HGDataType::Int;
|
|
||||||
}
|
|
||||||
if (isDouble(in)) {
|
|
||||||
return HGDataType::Double;
|
|
||||||
}
|
|
||||||
if (isString(in)) {
|
|
||||||
return HGDataType::String;
|
|
||||||
}
|
|
||||||
if (isChar(in)) {
|
|
||||||
return HGDataType::Char;
|
|
||||||
}
|
|
||||||
if (isBool(in)) {
|
|
||||||
return HGDataType::Bool;
|
|
||||||
}
|
|
||||||
return HGDataType::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGNodeType getNodeType(std::string in) {
|
|
||||||
if (getDataType(in) != HGDataType::None) {
|
|
||||||
return HGNodeType::Value;
|
|
||||||
}
|
|
||||||
if (in == "+") {
|
|
||||||
return HGNodeType::Add;
|
|
||||||
}
|
|
||||||
if (in == "puts") {
|
|
||||||
return HGNodeType::Puts;
|
|
||||||
}
|
|
||||||
if (in == "if") {
|
|
||||||
return HGNodeType::If;
|
|
||||||
}
|
|
||||||
if (in == "{") {
|
|
||||||
return HGNodeType::CodeBlockStart;
|
|
||||||
}
|
|
||||||
if (in == "}") {
|
|
||||||
return HGNodeType::CodeBlockEnd;
|
|
||||||
}
|
|
||||||
return HGNodeType::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Parser(std::vector<std::string> in) : tokensToParse(in) {}
|
|
||||||
|
|
||||||
HGNode parse() {
|
|
||||||
current = 0;
|
|
||||||
size = tokensToParse.size();
|
|
||||||
HGNode rootNode(HGNodeType::Root);
|
|
||||||
while (auto tokenopt = consume()) {
|
|
||||||
std::string token = tokenopt.value();
|
|
||||||
switch (getNodeType(token)) {
|
|
||||||
case HGNodeType::Value: {
|
|
||||||
switch (getDataType(token)) {
|
|
||||||
case HGDataType::Int: {
|
|
||||||
HGNode intNode(HGNodeType::Value);
|
|
||||||
intNode.setValue((int64_t) std::stoll(token));
|
|
||||||
rootNode.addNode(intNode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HGDataType::Double: {
|
|
||||||
HGNode doubleNode(HGNodeType::Value);
|
|
||||||
doubleNode.setValue(std::stod(token));
|
|
||||||
rootNode.addNode(doubleNode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HGDataType::String: {
|
|
||||||
HGNode stringNode(HGNodeType::Value);
|
|
||||||
stringNode.setValue(token.substr(1, token.size() - 2));
|
|
||||||
rootNode.addNode(stringNode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HGDataType::Char: {
|
|
||||||
HGNode charNode(HGNodeType::Value);
|
|
||||||
charNode.setValue(token[1]);
|
|
||||||
rootNode.addNode(charNode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HGDataType::Bool: {
|
|
||||||
HGNode boolNode(HGNodeType::Value);
|
|
||||||
boolNode.setValue(token == "true");
|
|
||||||
rootNode.addNode(boolNode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HGNodeType::Add: {
|
|
||||||
HGNode addNode(HGNodeType::Add);
|
|
||||||
addNode.addNode(rootNode.children.back());
|
|
||||||
rootNode.children.pop_back();
|
|
||||||
auto tokenopt = consume();
|
|
||||||
if (tokenopt) {
|
|
||||||
addNode.addNode(parseOneToken(tokenopt));
|
|
||||||
} else {
|
|
||||||
std::cout << "FEED ME MORE TOKENS\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
rootNode.addNode(addNode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HGNodeType::Puts: {
|
|
||||||
HGNode putsNode(HGNodeType::Puts);
|
|
||||||
std::vector<std::string> tokens;
|
|
||||||
while (auto tokenopt = consume()) {
|
|
||||||
if (tokenopt.value() == "\n") {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tokens.push_back(tokenopt.value());
|
|
||||||
}
|
|
||||||
auto children = Parser(tokens).parse();
|
|
||||||
for (auto& child : children.children) {
|
|
||||||
putsNode.addNode(child);
|
|
||||||
}
|
|
||||||
rootNode.addNode(putsNode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HGNodeType::If: {
|
|
||||||
HGNode ifNode(HGNodeType::If);
|
|
||||||
std::vector<std::string> tokens;
|
|
||||||
while (auto tokenopt = consume()) {
|
|
||||||
if (tokenopt.value() == "\n") {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tokens.push_back(tokenopt.value());
|
|
||||||
}
|
|
||||||
auto children = Parser(tokens).parse();
|
|
||||||
if (children.children.size() != 1) {
|
|
||||||
std::cout << "Too many or too little conditions for if\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
ifNode.addNode(children.children[0]);
|
|
||||||
tokens.clear();
|
|
||||||
size_t brackets = 1;
|
|
||||||
auto tokenopt = consume();
|
|
||||||
if (tokenopt) {
|
|
||||||
if (tokenopt.value() == "{") {
|
|
||||||
tokens.push_back(tokenopt.value());
|
|
||||||
while (auto tokenopt = consume()) {
|
|
||||||
tokens.push_back(tokenopt.value());
|
|
||||||
if (tokenopt.value() == "{") {
|
|
||||||
brackets++;
|
|
||||||
}
|
|
||||||
if (tokenopt.value() == "}") {
|
|
||||||
brackets--;
|
|
||||||
}
|
|
||||||
if (brackets == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::cout << "I want a code block\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::cout << "FEED ME MORE TOKENSSSSS\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HGNodeType::CodeBlockStart: {
|
|
||||||
HGNode codeBlockNode(HGNodeType::CodeBlock);
|
|
||||||
// WIP
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rootNode;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
GroundProgram assembleProgram(HGNode& rootNode) {
|
|
||||||
GroundProgram gp = groundCreateProgram();
|
|
||||||
auto code = rootNode.generateCode();
|
|
||||||
for (int i = 0; i < code.size(); i++) {
|
|
||||||
for (const auto& inst : code[i].code) {
|
|
||||||
groundAddInstructionToProgram(&gp, inst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return gp;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Parser
|
|
||||||
|
|
||||||
class Lexer {
|
|
||||||
std::string input;
|
|
||||||
size_t size;
|
|
||||||
size_t current;
|
|
||||||
|
|
||||||
std::optional<char> peek(int ahead = 1) {
|
|
||||||
if (current + ahead < size) {
|
|
||||||
return input[current + ahead];
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<char> consume() {
|
|
||||||
if (current < size) {
|
|
||||||
return input[current++];
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Lexer(std::string in) : input(in), size(in.size()) {};
|
|
||||||
std::vector<std::string> lex() {
|
|
||||||
current = 0;
|
|
||||||
std::vector<std::string> tokens;
|
|
||||||
std::string buf;
|
|
||||||
while (auto copt = consume()) {
|
|
||||||
char c = copt.value();
|
|
||||||
switch (c) {
|
|
||||||
// tokens which are not followed by anything
|
|
||||||
case '\n':
|
|
||||||
case '(':
|
|
||||||
case ')':
|
|
||||||
case '}':
|
|
||||||
{
|
|
||||||
if (!buf.empty()) {
|
|
||||||
tokens.push_back(buf);
|
|
||||||
buf.clear();
|
|
||||||
}
|
|
||||||
tokens.push_back(std::string(1, c));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// tokens which may be followed by either themselves
|
|
||||||
// or an equals sign
|
|
||||||
case '+':
|
|
||||||
case '-':
|
|
||||||
{
|
|
||||||
std::string newToken(1, c);
|
|
||||||
auto tokenopt = peek();
|
|
||||||
if (tokenopt) {
|
|
||||||
char token = tokenopt.value();
|
|
||||||
if (token == c || token == '=') {
|
|
||||||
newToken += token;
|
|
||||||
consume();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!buf.empty()) {
|
|
||||||
tokens.push_back(buf);
|
|
||||||
buf.clear();
|
|
||||||
}
|
|
||||||
tokens.push_back(newToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// tokens which may be followed by an equals sign
|
|
||||||
case '*':
|
|
||||||
case '/':
|
|
||||||
case '=':
|
|
||||||
{
|
|
||||||
std::string newToken(1, c);
|
|
||||||
auto tokenopt = peek();
|
|
||||||
if (tokenopt) {
|
|
||||||
char token = tokenopt.value();
|
|
||||||
if (token == '=') {
|
|
||||||
newToken += token;
|
|
||||||
consume();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!buf.empty()) {
|
|
||||||
tokens.push_back(buf);
|
|
||||||
buf.clear();
|
|
||||||
}
|
|
||||||
tokens.push_back(newToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// tokens which need a newline inserted for them
|
|
||||||
case '{':
|
|
||||||
{
|
|
||||||
if (!buf.empty()) {
|
|
||||||
tokens.push_back(buf);
|
|
||||||
buf.clear();
|
|
||||||
}
|
|
||||||
tokens.push_back(std::string(1, c));
|
|
||||||
tokens.push_back("\n");
|
|
||||||
}
|
|
||||||
// tokens which do not need to be included
|
|
||||||
case ' ':
|
|
||||||
{
|
|
||||||
if (!buf.empty()) {
|
|
||||||
tokens.push_back(buf);
|
|
||||||
buf.clear();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
buf += c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!buf.empty()) {
|
|
||||||
tokens.push_back(buf);
|
|
||||||
}
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace HighGround
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
if (argc < 2) {
|
|
||||||
std::cout << "Usage: " << argv[0] << " (file)\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
std::ifstream file(argv[1]);
|
|
||||||
std::ostringstream ss;
|
|
||||||
ss << file.rdbuf();
|
|
||||||
auto lexed = HighGround::Lexer(ss.str()).lex();
|
|
||||||
auto parsed = HighGround::Parser::Parser(lexed).parse();
|
|
||||||
GroundProgram program = HighGround::Parser::assembleProgram(parsed);
|
|
||||||
groundRunProgram(&program);
|
|
||||||
}
|
|
||||||
0
src/main.sols
Normal file
0
src/main.sols
Normal file
9
tests/closure.sols
Normal file
9
tests/closure.sols
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
def createClosure(int x) fun(int) int {
|
||||||
|
return lambda(int y) int {
|
||||||
|
return x + y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
myVar = createClosure(5)
|
||||||
|
|
||||||
|
puts myVar(3)
|
||||||
55
tests/compare.sols
Normal file
55
tests/compare.sols
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
if 1 == 1 {
|
||||||
|
puts "working"
|
||||||
|
}
|
||||||
|
|
||||||
|
if 1 == 2 {
|
||||||
|
puts "not working"
|
||||||
|
}
|
||||||
|
|
||||||
|
if 1 != 2 {
|
||||||
|
puts "working"
|
||||||
|
}
|
||||||
|
|
||||||
|
if 1 != 1 {
|
||||||
|
puts "not working"
|
||||||
|
}
|
||||||
|
|
||||||
|
if 2 > 1 {
|
||||||
|
puts "working"
|
||||||
|
}
|
||||||
|
|
||||||
|
if 1 > 2 {
|
||||||
|
puts "not working"
|
||||||
|
}
|
||||||
|
|
||||||
|
if 1 < 2 {
|
||||||
|
puts "working"
|
||||||
|
}
|
||||||
|
|
||||||
|
if 2 < 1 {
|
||||||
|
puts "not working"
|
||||||
|
}
|
||||||
|
|
||||||
|
if 2 >= 2 {
|
||||||
|
puts "working"
|
||||||
|
}
|
||||||
|
|
||||||
|
if 2 >= 1 {
|
||||||
|
puts "working"
|
||||||
|
}
|
||||||
|
|
||||||
|
if 2 >= 3 {
|
||||||
|
puts "not working"
|
||||||
|
}
|
||||||
|
|
||||||
|
if 2 <= 2 {
|
||||||
|
puts "working"
|
||||||
|
}
|
||||||
|
|
||||||
|
if 2 <= 3 {
|
||||||
|
puts "working"
|
||||||
|
}
|
||||||
|
|
||||||
|
if 3 <= 2 {
|
||||||
|
puts "not working"
|
||||||
|
}
|
||||||
11
tests/convert.sols
Normal file
11
tests/convert.sols
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
use conversions
|
||||||
|
use io
|
||||||
|
|
||||||
|
myString = "312"
|
||||||
|
myInt = 435
|
||||||
|
|
||||||
|
myNewString = intToString(myInt)
|
||||||
|
myNewInt = stringToInt(myString)
|
||||||
|
|
||||||
|
println(myNewString)
|
||||||
|
puts myNewInt
|
||||||
6
tests/count.sols
Normal file
6
tests/count.sols
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
number = 0
|
||||||
|
|
||||||
|
while number != 10 {
|
||||||
|
number = number + 1
|
||||||
|
puts number
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
puts "dingus"
|
|
||||||
puts 432
|
|
||||||
puts 3.141
|
|
||||||
puts 'c'
|
|
||||||
puts true
|
|
||||||
7
tests/data.sols
Normal file
7
tests/data.sols
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
puts "dingus"
|
||||||
|
puts 432
|
||||||
|
puts 3.141
|
||||||
|
puts 'c'
|
||||||
|
puts true
|
||||||
|
|
||||||
|
puts "now we have proper string lexing!!!!!11!!@!2!1@1@12!!!112!@"
|
||||||
15
tests/fib.sols
Normal file
15
tests/fib.sols
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
a = 0
|
||||||
|
b = 1
|
||||||
|
n = 92
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
while i != n {
|
||||||
|
temp = a + b
|
||||||
|
a = b
|
||||||
|
b = temp
|
||||||
|
|
||||||
|
i = i + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
puts a
|
||||||
6
tests/function.sols
Normal file
6
tests/function.sols
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
def add(int a, int b) int {
|
||||||
|
puts "testing"
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
|
||||||
|
puts add(1, 2)
|
||||||
7
tests/if.sols
Normal file
7
tests/if.sols
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
if 1 == 1 {
|
||||||
|
puts "huzzah"
|
||||||
|
}
|
||||||
|
|
||||||
|
if 5 == 10 {
|
||||||
|
puts "aww"
|
||||||
|
}
|
||||||
7
tests/inlineground.sols
Normal file
7
tests/inlineground.sols
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
result = 0
|
||||||
|
ground {
|
||||||
|
println "dingus"
|
||||||
|
add 3 2 &result
|
||||||
|
}
|
||||||
|
|
||||||
|
puts result
|
||||||
15
tests/input.sols
Normal file
15
tests/input.sols
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
use io
|
||||||
|
|
||||||
|
accessNotGranted = true
|
||||||
|
|
||||||
|
while accessNotGranted {
|
||||||
|
password = input("Password: ")
|
||||||
|
if password == "dingus" {
|
||||||
|
accessNotGranted = false
|
||||||
|
}
|
||||||
|
if password != "dingus" {
|
||||||
|
puts "Incorrect password!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
puts "Welcome!"
|
||||||
@@ -1 +1,3 @@
|
|||||||
|
use io
|
||||||
|
|
||||||
println("dingus")
|
println("dingus")
|
||||||
3
tests/set.sols
Normal file
3
tests/set.sols
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
x = 5
|
||||||
|
y = 10
|
||||||
|
puts x + y
|
||||||
32
tests/struct.sols
Normal file
32
tests/struct.sols
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
struct Person {
|
||||||
|
protected name = ""
|
||||||
|
private age = 0
|
||||||
|
|
||||||
|
def greet() string {
|
||||||
|
return "Hello, " + self.name + "!"
|
||||||
|
}
|
||||||
|
|
||||||
|
def dance() string {
|
||||||
|
return "Dancing..."
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(string name, int age) {
|
||||||
|
self.name = name
|
||||||
|
self.age = age
|
||||||
|
}
|
||||||
|
|
||||||
|
destructor {
|
||||||
|
// We don't need to do anything here.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
max = Person("Max", 16)
|
||||||
|
|
||||||
|
puts max
|
||||||
|
puts max.greet()
|
||||||
|
puts max.name
|
||||||
|
// puts max.age (causes compile time error, age is private)
|
||||||
|
// max.name = "Maximilian" (causes compile time error, name is protected)
|
||||||
|
|
||||||
|
max.dance()
|
||||||
3
tests/while.sols
Normal file
3
tests/while.sols
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
while 1 == 1 {
|
||||||
|
puts "yay infinite loop"
|
||||||
|
}
|
||||||
1
vim/ftdetect/solstice.vim
Normal file
1
vim/ftdetect/solstice.vim
Normal file
@@ -0,0 +1 @@
|
|||||||
|
au BufRead,BufNewFile *.sols setfiletype solstice
|
||||||
45
vim/syntax/solstice.vim
Normal file
45
vim/syntax/solstice.vim
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
" Vim highlight file for Solstice (.sols)
|
||||||
|
|
||||||
|
if exists("b:current_syntax")
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Keywords
|
||||||
|
syn keyword solsKeyword puts if while def lambda return use struct ground
|
||||||
|
syn keyword solsBool true false
|
||||||
|
|
||||||
|
" Types
|
||||||
|
syn keyword solsType int double string char bool fun template object
|
||||||
|
|
||||||
|
" Strings and chars
|
||||||
|
syn region solsString start=/"/ skip=/\\"/ end=/"/
|
||||||
|
syn region solsChar start=/'/ skip=/\\'/ end=/'/
|
||||||
|
|
||||||
|
" Numbers
|
||||||
|
syn match solsFloat /\<[0-9]\+\.[0-9]*\>/
|
||||||
|
syn match solsInt /\<[0-9]\+\>/
|
||||||
|
|
||||||
|
" Operators
|
||||||
|
syn match solsOperator /+\|-\|\*\|\/\|=\|!\|>\|<\|+=\|-=\|\*=\|\/=\|++\|--\|==\|!=\|>=\|<=/
|
||||||
|
|
||||||
|
" Delimiters
|
||||||
|
syn match solsDelimiter /[{}(),;]/
|
||||||
|
|
||||||
|
" Comments
|
||||||
|
syn match solsComment /\/\/.*$/
|
||||||
|
syn match solsComment /#.*$/
|
||||||
|
|
||||||
|
" Highlight links
|
||||||
|
hi def link solsKeyword Keyword
|
||||||
|
hi def link solsBool Boolean
|
||||||
|
hi def link solsType Type
|
||||||
|
hi def link solsString String
|
||||||
|
hi def link solsChar Character
|
||||||
|
hi def link solsFloat Float
|
||||||
|
hi def link solsInt Number
|
||||||
|
hi def link solsOperator Operator
|
||||||
|
hi def link solsDelimiter Delimiter
|
||||||
|
hi def link solsComment Comment
|
||||||
|
|
||||||
|
let b:current_syntax = "solstice"
|
||||||
|
|
||||||
Reference in New Issue
Block a user