Compare commits
34 Commits
Author | SHA1 | Date | |
---|---|---|---|
c952be1fe6 | |||
1c5ca8d201 | |||
e56e6de911 | |||
38b17e7db5 | |||
e74e5ea548 | |||
f5140e3833 | |||
c01dd470e1 | |||
16660c6a8d | |||
5bd8519517 | |||
2f706e2285 | |||
db99b9ac9f | |||
e906734aca | |||
8da5a2bf93 | |||
e9600d8500 | |||
1c0dfcc4b7 | |||
f7f3972248 | |||
50d83aa228 | |||
14758df1ab | |||
b19b4123d8 | |||
28a9e389fa | |||
e4cc6b2f14 | |||
bb753e97d4 | |||
4cd4d9080d | |||
52eadaa9c3 | |||
db0c362efb | |||
3a8600b481 | |||
c39967a72f | |||
163f85b896 | |||
09033cd432 | |||
566d3aa0fb | |||
f8397e85d4 | |||
3f2482d7ea | |||
2e388c6e68 | |||
f43f79b869 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
ground
|
||||
Bobfile
|
||||
|
2
Bobfile
2
Bobfile
@@ -1,5 +1,5 @@
|
||||
compiler "g++";
|
||||
binary "ground";
|
||||
source "src/main.cpp";
|
||||
flag "O3";
|
||||
flag "Ofast";
|
||||
compile;
|
||||
|
@@ -8,7 +8,7 @@ Ground is an interpreter which processes and interprets Ground instructions. It
|
||||
|
||||
* **Simple syntax:** Ground doesn't have very many features, and that's intentional. It makes Ground easy to learn, and keeps it speedy.
|
||||
* **Super speed:** Ground code is faster than Python and JavaScript, and nearly as fast as C++ and Rust, while still being interpreted. (Tested using tests/to1000.grnd)
|
||||
* **Tiny interpreter:** Ground contains 761 lines of code (and 233 lines of comments) at the time of writing, and compiles in seconds.
|
||||
* **Tiny interpreter:** Ground contains 1482 lines of code (and 382 lines of comments) at the time of writing, and compiles in seconds.
|
||||
* **Portable:** Ground's code only uses features from the C++ standard library, using features from C++17 and prior.
|
||||
|
||||
## How do I get started?
|
||||
@@ -16,7 +16,7 @@ Ground is an interpreter which processes and interprets Ground instructions. It
|
||||
Clone the repo and compile with your favourite C++ compiler:
|
||||
|
||||
```
|
||||
g++ src/main.cpp -std=C++17 -O3 -o ground
|
||||
g++ src/main.cpp -std=c++17 -O3 -o ground
|
||||
```
|
||||
|
||||
(You can omit the -std flag on systems which default to the latest standard, and the -O3 flag if you're fine with a slightly slower interpreter.)
|
||||
|
107
docs/demos/calc.grnd
Executable file
107
docs/demos/calc.grnd
Executable file
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env ground
|
||||
|
||||
@begin
|
||||
stdout "Calculation: "
|
||||
stdin &calc
|
||||
getstrsize $calc &calcsize
|
||||
set &counter 0
|
||||
set &left ""
|
||||
set &right ""
|
||||
set &operator ' '
|
||||
set &isRight false
|
||||
|
||||
## Preprocessing
|
||||
|
||||
# Loop to parse input
|
||||
@loopstart
|
||||
getstrcharat $calc $counter &char
|
||||
|
||||
# Remove any spaces (they're inconvenient)
|
||||
equal $char ' ' &cond
|
||||
if $cond %doneif
|
||||
|
||||
# Check for operators
|
||||
# '+' operator
|
||||
inequal '+' $char &cond
|
||||
if $cond %minusOpCheck
|
||||
set &operator $char
|
||||
set &isRight true
|
||||
jump %doneif
|
||||
|
||||
@minusOpCheck
|
||||
# '-' operator
|
||||
inequal '-' $char &cond
|
||||
if $cond %multiplyOpCheck
|
||||
set &operator $char
|
||||
set &isRight true
|
||||
jump %doneif
|
||||
|
||||
@multiplyOpCheck
|
||||
# '*' operator
|
||||
inequal '*' $char &cond
|
||||
if $cond %divideOpCheck
|
||||
set &operator $char
|
||||
set &isRight true
|
||||
jump %doneif
|
||||
|
||||
@divideOpCheck
|
||||
# '/' operator
|
||||
inequal '/' $char &cond
|
||||
if $cond %endOpChecks
|
||||
set &operator $char
|
||||
set &isRight true
|
||||
jump %doneif
|
||||
|
||||
@endOpChecks
|
||||
if $isRight %isRight
|
||||
add $left $char &left
|
||||
jump %doneif
|
||||
@isRight
|
||||
add $right $char &right
|
||||
@doneif
|
||||
add 1 $counter &counter
|
||||
inequal $counter $calcsize &cond
|
||||
if $cond %loopstart
|
||||
# End loop
|
||||
|
||||
## Computing
|
||||
|
||||
# Convert types
|
||||
stod $left &left
|
||||
stod $right &right
|
||||
|
||||
# Calculations
|
||||
# Adding
|
||||
inequal $operator '+' &cond
|
||||
if $cond %subtract
|
||||
add $left $right &result
|
||||
stdlnout $result
|
||||
jump %begin
|
||||
|
||||
# Subtracting
|
||||
@subtract
|
||||
inequal $operator '-' &cond
|
||||
if $cond %multiply
|
||||
subtract $left $right &result
|
||||
stdlnout $result
|
||||
jump %begin
|
||||
|
||||
# Multiplying
|
||||
@multiply
|
||||
inequal $operator '*' &cond
|
||||
if $cond %divide
|
||||
multiply $left $right &result
|
||||
stdlnout $result
|
||||
jump %begin
|
||||
|
||||
# Dividing
|
||||
@divide
|
||||
inequal $operator '/' &cond
|
||||
if $cond %error
|
||||
divide $left $right &result
|
||||
stdlnout $result
|
||||
jump %begin
|
||||
|
||||
@error
|
||||
stdlnout "Uh oh something terribly terrible happened lmao"
|
||||
jump %begin
|
21
docs/library-guide.md
Normal file
21
docs/library-guide.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Guide to Writing Libraries in Ground
|
||||
|
||||
Ground has a "use" keyword which allows you to import libraries written in Ground, executing the code, and importing functions for use. This makes building reproducable bits of code very easy.
|
||||
|
||||
This is a guide of best practices which should be followed.
|
||||
|
||||
## .grnd file extension
|
||||
|
||||
The Ground interpreter will automatically append ".grnd" when you use a library. If you write `use "myLibrary"` Ground will look for "myLibrary.grnd". This is a must-do.
|
||||
|
||||
## camelCase Function and File Names
|
||||
|
||||
For consistency, please use camelCase (with a lower case first letter) when naming functions and file names.
|
||||
|
||||
## Don't use spaces
|
||||
|
||||
It is impossible to use spaces in Ground function names. Please do not use spaces in file names, even though it will work.
|
||||
|
||||
## Use functions for most operations
|
||||
|
||||
Where possible, create functions to do everything needed with your library. You can include some code for initialisation, but don't do the entirety of your operations outside of your functions.
|
170
docs/syntax.md
170
docs/syntax.md
@@ -1,6 +1,6 @@
|
||||
## Ground Syntax Guide
|
||||
|
||||
### General syntax
|
||||
## General syntax
|
||||
|
||||
Ground uses simple instructions and arguments to run code.
|
||||
|
||||
@@ -32,12 +32,38 @@ Reference a line (a line reference) with a percent symbol before a line number:
|
||||
jump %10
|
||||
```
|
||||
|
||||
### Keywords
|
||||
Alternatively, set a label:
|
||||
|
||||
```
|
||||
@myLabel # The '@' symbol denotes setting a label
|
||||
```
|
||||
|
||||
and jump to that (setting labels will be discussed below):
|
||||
|
||||
```
|
||||
jump %myLabel
|
||||
```
|
||||
|
||||
Reference a list (a list reference) with an asterisk:
|
||||
|
||||
```
|
||||
setlist *myList $value1 $value2 # and so on
|
||||
```
|
||||
|
||||
Add comments with a `#`:
|
||||
|
||||
```
|
||||
# This is a comment
|
||||
```
|
||||
|
||||
## Keywords
|
||||
|
||||
Note: &var can be replaced with any direct reference. $value can be replaced with a literal value or a value reference. %1 can be replaced with a line reference.
|
||||
|
||||
Note: In most of these functions, if a direct reference is used, the value outputted by that function will be avaliable at that variable. Any existing value inside that variable will be overwritten.
|
||||
|
||||
### Control Flow
|
||||
|
||||
#### if
|
||||
|
||||
Make a decision based on a boolean. If the boolean is true, jumps to the line referenced.
|
||||
@@ -54,7 +80,9 @@ Usage: `jump %1`
|
||||
|
||||
Ends the program. Requires an integer for a status code.
|
||||
|
||||
Usage: `end $value`
|
||||
Usage: `end $intvalue`
|
||||
|
||||
### I/O
|
||||
|
||||
#### stdin
|
||||
|
||||
@@ -74,12 +102,60 @@ Allows output to the console, appending a new line at the end.
|
||||
|
||||
Usage: `stdlnout $value`
|
||||
|
||||
### Variables and Lists
|
||||
|
||||
#### set
|
||||
|
||||
Allows you to set a variable to a value.
|
||||
|
||||
Usage: `set &var $value`
|
||||
|
||||
#### setlist
|
||||
|
||||
Allows you to initialize a list.
|
||||
|
||||
Usage: `setlist *list $value1 $value2 $value3...`
|
||||
|
||||
#### setlistat
|
||||
|
||||
Sets a list item at an index. The item at the index must already exist. Lists are index 0.
|
||||
|
||||
Usage: `setlistat *list $intvalue $value`
|
||||
|
||||
#### getlistat
|
||||
|
||||
Gets a list item at an index, and puts it in the variable provided. The item at the index must already exist. Lists are index 0.
|
||||
|
||||
Usage: `getlistat *list $intvalue &var`
|
||||
|
||||
#### getlistsize
|
||||
|
||||
Gets the size of a list and puts it in the variable provided.
|
||||
|
||||
Usage: `getlistsize *list &var`
|
||||
|
||||
#### listappend
|
||||
|
||||
Appends an item to a list.
|
||||
|
||||
Usage: `listappend *list $var`
|
||||
|
||||
### String Operations
|
||||
|
||||
#### getstrsize
|
||||
|
||||
Gets the size of a string and puts it in the variable provided.
|
||||
|
||||
Usage: `getstrsize $stringvalue &var`
|
||||
|
||||
#### getstrcharat
|
||||
|
||||
Gets a character at a certain position in a string and saves it to a variable.
|
||||
|
||||
Usage: `getstrcharat $stringvalue $intvalue &var`
|
||||
|
||||
### Maths
|
||||
|
||||
#### add
|
||||
|
||||
Adds two numbers. Numbers mean an integer or a double. Outputs to a direct reference.
|
||||
@@ -104,6 +180,8 @@ Divides two numbers. Numbers mean an integer or a double. Outputs to a direct re
|
||||
|
||||
Usage: `divide $value $value &var`
|
||||
|
||||
### Comparisons
|
||||
|
||||
#### equal
|
||||
|
||||
Checks if two values are equal. Outputs a boolean to a direct reference.
|
||||
@@ -116,6 +194,12 @@ Checks if two values are not equal. Outputs a boolean to a direct reference.
|
||||
|
||||
Usage: `inequal $value $value &var`
|
||||
|
||||
#### not
|
||||
|
||||
Negates a boolean.
|
||||
|
||||
Usage: `not $value &var`
|
||||
|
||||
#### greater
|
||||
|
||||
Checks if the left value is greater than the right value. Outputs a boolean to a direct reference.
|
||||
@@ -127,3 +211,83 @@ Usage: `greater $value $value &var`
|
||||
Checks if the left value is lesser than the right value. Outputs a boolean to a direct reference.
|
||||
|
||||
Usage: `lesser $value $value &var`
|
||||
|
||||
### Type Conversions
|
||||
|
||||
#### stoi
|
||||
|
||||
Converts a string to an integer. Throws an error if the string cannot be turned into an integer.
|
||||
|
||||
Usage: `stoi $stringvalue &var`
|
||||
|
||||
#### stod
|
||||
|
||||
Converts a string to a double. Throws an error if the string cannot be turned into a double.
|
||||
|
||||
Usage: `stod $stringvalue &var`
|
||||
|
||||
#### tostring
|
||||
|
||||
Converts any type to a string.
|
||||
|
||||
Usage: `tostring $value &var`
|
||||
|
||||
### Functions and function specific features (Experimental, please report bugs!)
|
||||
|
||||
Some symbols specific to this category:
|
||||
|
||||
* `!function`: A function reference
|
||||
|
||||
* `-type`: A type reference. Can be one of the following: "-string", "-char", "-int", "-double", "-bool"
|
||||
|
||||
#### fun
|
||||
|
||||
Defines a function. All code between `fun` and `endfun` will be included in the function.
|
||||
|
||||
Usage: `fun -type !functionname -type &var -type &var -type &var # and so on...`
|
||||
|
||||
Usage note: The first type specified before the function name must be the return type. The type displayed before all vars shows what type that variable must be.
|
||||
|
||||
#### return
|
||||
|
||||
Returns back to the main program (or other function that called this function). Also returns a value, which must be of the type defined when defining the function.
|
||||
|
||||
Usage: `return $value`
|
||||
|
||||
#### endfun
|
||||
|
||||
Ends a function definition. When a function reaches the end the argument list will be cleared.
|
||||
|
||||
Usage: `endfun`
|
||||
|
||||
#### pusharg
|
||||
|
||||
Adds a value to the argument list which will be passed to the function when it is called.
|
||||
|
||||
Usage: `pusharg $value`
|
||||
|
||||
#### call
|
||||
|
||||
Calls a function, with all the arguments in the argument list. The return value will be put in the specified variable.
|
||||
|
||||
Usage: `call !function &var
|
||||
|
||||
### Interacting with Libraries
|
||||
|
||||
#### use (Experimental, please report bugs!)
|
||||
|
||||
Attempts to import another Ground program. Gets inserted wherever the use statement is. Any code (including code outside function declarations) will be executed.
|
||||
|
||||
Note: Ground will check the directory where the program is being run from when trying to find imported programs. If that fails, it will check the directory set in the $GROUND_LIBS environment variable set by your system. The '.grnd' extension is appended automatically.
|
||||
|
||||
Usage: `use $stringvalue`
|
||||
|
||||
#### extern (Experimental, please report bugs!)
|
||||
|
||||
Attempts to import a shared object library written for Ground. All functions in the external library will be usable with `call`.
|
||||
|
||||
Note: Ground will check the directory set in the $GROUND_LIBS environment variable set by your system. The '.so' (Linux), '.dylib' (macOS), or '.dll' (Windows) extension is appended automatically.
|
||||
|
||||
Documentation on how to do external libraries coming soon.
|
||||
|
||||
Usage: `extern $stringvalue`
|
||||
|
25
docs/writing-a-program.md
Normal file
25
docs/writing-a-program.md
Normal file
@@ -0,0 +1,25 @@
|
||||
## Writing programs with Ground (WORK IN PROGRESS GUIDE)
|
||||
|
||||
Ground is a very easy language to learn. In this guide, you will learn how to write a simple calculator in Ground, as well as best practices (which there aren't many of, since Ground is so simple).
|
||||
|
||||
Note: This assumes you've read and understand the syntax.md document in this folder.
|
||||
|
||||
### Let's start!
|
||||
|
||||
Open a new file with the `.grnd` extension. Should look something like this:
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
(Real empty in that file.)
|
||||
|
||||
Let's add some code! Create a label for the start, since we'll loop back once we've calculated, and ask for the user's input:
|
||||
|
||||
```
|
||||
@start
|
||||
stdout "Calculation: "
|
||||
stdin &calc
|
||||
```
|
||||
|
||||
At the calc variable, we have whatever the user typed in. This should look something like `9+10`, `1 / 3` or who knows what else. But first we should organise this data. Let's create a loop to iterate through this input, and a counter to keep moving forward:
|
43
extlibs/file.cpp
Normal file
43
extlibs/file.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "ground_lib.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
|
||||
GroundValue readFile(GroundValue* args, int arg_count) {
|
||||
VALIDATE_ARGS_1(GROUND_STRING);
|
||||
|
||||
std::ifstream ffile(GET_STRING(args[0]));
|
||||
|
||||
std::string tmp;
|
||||
std::string out;
|
||||
|
||||
while (std::getline(ffile, tmp)) {
|
||||
out += tmp + "\n";
|
||||
}
|
||||
|
||||
return ground_string_val(out);
|
||||
}
|
||||
|
||||
GroundValue writeFile(GroundValue* args, int arg_count) {
|
||||
VALIDATE_ARGS_2(GROUND_STRING, GROUND_STRING);
|
||||
|
||||
std::ofstream file(GET_STRING(args[0]));
|
||||
if (file.good()) {
|
||||
file << GET_STRING(args[1]);
|
||||
} else {
|
||||
std::cout << "File isn't good for writing in" << std::endl;
|
||||
return GROUND_BOOL_VAL(false);
|
||||
}
|
||||
|
||||
return GROUND_BOOL_VAL(true);
|
||||
}
|
||||
|
||||
GROUND_LIBRARY_INTERFACE()
|
||||
|
||||
GROUND_LIBRARY_INIT()
|
||||
REGISTER_GROUND_FUNCTION(readFile);
|
||||
REGISTER_GROUND_FUNCTION(writeFile);
|
||||
GROUND_LIBRARY_INIT_END()
|
||||
|
||||
GROUND_LIBRARY_CLEANUP()
|
||||
GROUND_LIBRARY_CLEANUP_END()
|
193
extlibs/ground_lib.h
Normal file
193
extlibs/ground_lib.h
Normal file
@@ -0,0 +1,193 @@
|
||||
#ifndef GROUND_LIB_H
|
||||
#define GROUND_LIB_H
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
// Ground types - must match the interpreter
|
||||
typedef enum {
|
||||
GROUND_INT,
|
||||
GROUND_DOUBLE,
|
||||
GROUND_BOOL,
|
||||
GROUND_STRING,
|
||||
GROUND_CHAR
|
||||
} GroundType;
|
||||
|
||||
typedef struct {
|
||||
GroundType type;
|
||||
union {
|
||||
int int_val;
|
||||
double double_val;
|
||||
int bool_val;
|
||||
char* string_val;
|
||||
char char_val;
|
||||
} data;
|
||||
} GroundValue;
|
||||
|
||||
// Helper macros for creating GroundValue objects
|
||||
#define GROUND_INT_VAL(x) ({ GroundValue v; v.type = GROUND_INT; v.data.int_val = (x); v; })
|
||||
#define GROUND_DOUBLE_VAL(x) ({ GroundValue v; v.type = GROUND_DOUBLE; v.data.double_val = (x); v; })
|
||||
#define GROUND_BOOL_VAL(x) ({ GroundValue v; v.type = GROUND_BOOL; v.data.bool_val = (x) ? 1 : 0; v; })
|
||||
#define GROUND_CHAR_VAL(x) ({ GroundValue v; v.type = GROUND_CHAR; v.data.char_val = (x); v; })
|
||||
|
||||
// Helper function for creating string values
|
||||
inline GroundValue ground_string_val(const std::string& str) {
|
||||
GroundValue v;
|
||||
v.type = GROUND_STRING;
|
||||
char* result_str = new char[str.length() + 1];
|
||||
std::strcpy(result_str, str.c_str());
|
||||
v.data.string_val = result_str;
|
||||
return v;
|
||||
}
|
||||
|
||||
// Helper function for creating string values from C strings
|
||||
inline GroundValue ground_cstring_val(const char* str) {
|
||||
GroundValue v;
|
||||
v.type = GROUND_STRING;
|
||||
if (str) {
|
||||
size_t len = std::strlen(str);
|
||||
char* result_str = new char[len + 1];
|
||||
std::strcpy(result_str, str);
|
||||
v.data.string_val = result_str;
|
||||
} else {
|
||||
v.data.string_val = nullptr;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// Helper macros for type checking
|
||||
#define IS_INT(v) ((v).type == GROUND_INT)
|
||||
#define IS_DOUBLE(v) ((v).type == GROUND_DOUBLE)
|
||||
#define IS_BOOL(v) ((v).type == GROUND_BOOL)
|
||||
#define IS_STRING(v) ((v).type == GROUND_STRING)
|
||||
#define IS_CHAR(v) ((v).type == GROUND_CHAR)
|
||||
|
||||
// Helper macros for extracting values
|
||||
#define GET_INT(v) ((v).data.int_val)
|
||||
#define GET_DOUBLE(v) ((v).data.double_val)
|
||||
#define GET_BOOL(v) ((v).data.bool_val != 0)
|
||||
#define GET_STRING(v) ((v).data.string_val)
|
||||
#define GET_CHAR(v) ((v).data.char_val)
|
||||
|
||||
// Helper macros for argument validation
|
||||
#define REQUIRE_ARGS(count) \
|
||||
if (arg_count < (count)) { \
|
||||
std::cerr << "Error: Expected at least " << (count) << " arguments, got " << arg_count << std::endl; \
|
||||
return GROUND_BOOL_VAL(false); \
|
||||
}
|
||||
|
||||
#define REQUIRE_TYPE(arg_index, expected_type) \
|
||||
if (args[arg_index].type != expected_type) { \
|
||||
std::cerr << "Error: Argument " << (arg_index + 1) << " must be of type " << #expected_type << std::endl; \
|
||||
return GROUND_BOOL_VAL(false); \
|
||||
}
|
||||
|
||||
// Convenience macro for checking both arg count and types
|
||||
#define VALIDATE_ARGS_1(type1) \
|
||||
REQUIRE_ARGS(1); \
|
||||
REQUIRE_TYPE(0, type1);
|
||||
|
||||
#define VALIDATE_ARGS_2(type1, type2) \
|
||||
REQUIRE_ARGS(2); \
|
||||
REQUIRE_TYPE(0, type1); \
|
||||
REQUIRE_TYPE(1, type2);
|
||||
|
||||
#define VALIDATE_ARGS_3(type1, type2, type3) \
|
||||
REQUIRE_ARGS(3); \
|
||||
REQUIRE_TYPE(0, type1); \
|
||||
REQUIRE_TYPE(1, type2); \
|
||||
REQUIRE_TYPE(2, type3);
|
||||
|
||||
// Function registration helpers
|
||||
class GroundLibrary {
|
||||
private:
|
||||
std::vector<std::string> function_names;
|
||||
std::vector<void*> function_pointers;
|
||||
|
||||
public:
|
||||
void register_function(const std::string& name, void* ptr) {
|
||||
function_names.push_back(name);
|
||||
function_pointers.push_back(ptr);
|
||||
}
|
||||
|
||||
const char** get_function_names() {
|
||||
static std::vector<const char*> names;
|
||||
names.clear();
|
||||
for (const auto& name : function_names) {
|
||||
names.push_back(name.c_str());
|
||||
}
|
||||
names.push_back(nullptr); // Null terminator
|
||||
return names.data();
|
||||
}
|
||||
|
||||
void* get_function(const char* name) {
|
||||
for (size_t i = 0; i < function_names.size(); i++) {
|
||||
if (function_names[i] == name) {
|
||||
return function_pointers[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
// Global library instance
|
||||
extern GroundLibrary ground_lib_registry;
|
||||
|
||||
// Macro to register functions easily
|
||||
#define REGISTER_GROUND_FUNCTION(func_name) \
|
||||
ground_lib_registry.register_function(#func_name, (void*)func_name)
|
||||
|
||||
// Macro to define the library interface
|
||||
#define GROUND_LIBRARY_INTERFACE() \
|
||||
GroundLibrary ground_lib_registry; \
|
||||
extern "C" { \
|
||||
const char** ground_get_functions() { \
|
||||
return ground_lib_registry.get_function_names(); \
|
||||
} \
|
||||
void* ground_get_function(const char* name) { \
|
||||
return ground_lib_registry.get_function(name); \
|
||||
} \
|
||||
}
|
||||
|
||||
// Optional initialization macro
|
||||
#define GROUND_LIBRARY_INIT() \
|
||||
extern "C" { \
|
||||
void ground_lib_init() {
|
||||
|
||||
#define GROUND_LIBRARY_INIT_END() \
|
||||
} \
|
||||
}
|
||||
|
||||
// Optional cleanup macro
|
||||
#define GROUND_LIBRARY_CLEANUP() \
|
||||
extern "C" { \
|
||||
void ground_lib_cleanup() {
|
||||
|
||||
#define GROUND_LIBRARY_CLEANUP_END() \
|
||||
} \
|
||||
}
|
||||
|
||||
// Utility function to print GroundValue for debugging
|
||||
inline void debug_print_ground_value(const GroundValue& v) {
|
||||
switch (v.type) {
|
||||
case GROUND_INT:
|
||||
std::cout << "INT: " << v.data.int_val << std::endl;
|
||||
break;
|
||||
case GROUND_DOUBLE:
|
||||
std::cout << "DOUBLE: " << v.data.double_val << std::endl;
|
||||
break;
|
||||
case GROUND_BOOL:
|
||||
std::cout << "BOOL: " << (v.data.bool_val ? "true" : "false") << std::endl;
|
||||
break;
|
||||
case GROUND_STRING:
|
||||
std::cout << "STRING: " << (v.data.string_val ? v.data.string_val : "(null)") << std::endl;
|
||||
break;
|
||||
case GROUND_CHAR:
|
||||
std::cout << "CHAR: '" << v.data.char_val << "'" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GROUND_LIB_H
|
45
extlibs/request.cpp
Normal file
45
extlibs/request.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "ground_lib.h"
|
||||
|
||||
#include <cpr/cpr.h>
|
||||
#include <cpr/interface.h>
|
||||
#include <fstream>
|
||||
|
||||
GroundValue simpleRequest(GroundValue* args, int arg_count) {
|
||||
VALIDATE_ARGS_1(GROUND_STRING);
|
||||
|
||||
cpr::Response r = cpr::Get(cpr::Url(GET_STRING(args[0])));
|
||||
|
||||
if (!(r.status_code >= 200 && r.status_code < 300)) {
|
||||
return ground_string_val("Error code " + std::to_string(r.status_code));
|
||||
}
|
||||
|
||||
return ground_string_val(r.text);
|
||||
}
|
||||
|
||||
GroundValue saveContents(GroundValue* args, int arg_count) {
|
||||
VALIDATE_ARGS_2(GROUND_STRING, GROUND_STRING);
|
||||
|
||||
std::ofstream file(GET_STRING(args[1]), std::ios::binary);
|
||||
|
||||
if (file.good()) {
|
||||
cpr::Response r = cpr::Download(file, cpr::Url{GET_STRING(args[0])});
|
||||
|
||||
if (r.status_code >= 200 && r.status_code < 300) {
|
||||
return GROUND_BOOL_VAL(false);
|
||||
}
|
||||
} else {
|
||||
return GROUND_BOOL_VAL(false);
|
||||
}
|
||||
|
||||
return GROUND_BOOL_VAL(true);
|
||||
}
|
||||
|
||||
GROUND_LIBRARY_INTERFACE()
|
||||
|
||||
GROUND_LIBRARY_INIT()
|
||||
REGISTER_GROUND_FUNCTION(simpleRequest);
|
||||
REGISTER_GROUND_FUNCTION(saveContents);
|
||||
GROUND_LIBRARY_INIT_END()
|
||||
|
||||
GROUND_LIBRARY_CLEANUP()
|
||||
GROUND_LIBRARY_CLEANUP_END()
|
1266
src/main.cpp
1266
src/main.cpp
File diff suppressed because it is too large
Load Diff
12
tests/args.grnd
Executable file
12
tests/args.grnd
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env ground
|
||||
stdlnout "Program args: "
|
||||
getlistsize *args &argsSize
|
||||
set &counter 0
|
||||
@loopstart
|
||||
equal $counter $argsSize &bool
|
||||
if $bool %end
|
||||
getlistat *args $counter &item
|
||||
stdlnout $item
|
||||
add 1 $counter &counter
|
||||
jump %loopstart
|
||||
@end
|
89
tests/everything.grnd
Normal file
89
tests/everything.grnd
Normal file
@@ -0,0 +1,89 @@
|
||||
# I/O
|
||||
|
||||
stdlnout "Hello there!"
|
||||
stdout "What is your name? "
|
||||
stdin &name
|
||||
add "Hello, " $name &out
|
||||
stdlnout $out
|
||||
|
||||
# Types
|
||||
stdlnout "dingus"
|
||||
stdlnout 7
|
||||
stdlnout 3.14159
|
||||
stdlnout true
|
||||
stdlnout 'e'
|
||||
|
||||
# Variables
|
||||
|
||||
set &testVar "This is a test"
|
||||
stdlnout $testVar
|
||||
|
||||
# Lists
|
||||
|
||||
setlist *testList "Item 1" "Another Item" "Item the Third"
|
||||
getlistat *testList 2 &tmp
|
||||
stdlnout $tmp
|
||||
|
||||
setlistat *testList 1 "I changed this item"
|
||||
getlistat *testList 1 &tmp
|
||||
stdlnout $tmp
|
||||
|
||||
listappend *testList "I appended this item"
|
||||
getlistat *testList 3 &tmp
|
||||
stdlnout $tmp
|
||||
|
||||
getlistsize *testList &tmp
|
||||
stdlnout $tmp
|
||||
|
||||
# String Operations
|
||||
|
||||
set &testStr "dingus"
|
||||
|
||||
getstrsize $testStr &tmp
|
||||
stdlnout $tmp
|
||||
|
||||
getstrcharat $testStr 3 &tmp
|
||||
stdlnout $tmp
|
||||
|
||||
# Maths
|
||||
|
||||
add 1 1 &tmp
|
||||
stdlnout $tmp
|
||||
|
||||
subtract 10 5 &tmp
|
||||
stdlnout $tmp
|
||||
|
||||
multiply 15 15 &tmp
|
||||
stdlnout $tmp
|
||||
|
||||
divide 36 4 &tmp
|
||||
stdlnout $tmp
|
||||
|
||||
# Comparisons
|
||||
|
||||
equal 5 5 &tmp
|
||||
stdlnout $tmp
|
||||
|
||||
inequal 5 5 &tmp
|
||||
stdlnout $tmp
|
||||
|
||||
greater 10 5 &tmp
|
||||
stdlnout $tmp
|
||||
|
||||
lesser 10 5 &tmp
|
||||
stdlnout $tmp
|
||||
|
||||
# Control flow
|
||||
|
||||
set &counter 0
|
||||
|
||||
@myLabel
|
||||
add $counter 1 &counter
|
||||
stdlnout $counter
|
||||
inequal $counter 10 &case
|
||||
if $case %myLabel
|
||||
|
||||
# That's it!
|
||||
|
||||
stdlnout "Everything ran! Check the output to see if it is what is expected."
|
||||
end 0
|
19
tests/functions.grnd
Normal file
19
tests/functions.grnd
Normal file
@@ -0,0 +1,19 @@
|
||||
fun -bool !jumpy
|
||||
stdlnout "This is the jumpy function"
|
||||
set &counter 0
|
||||
jump %inloop
|
||||
@jumpback
|
||||
stdlnout "Yay I jumped!"
|
||||
@inloop
|
||||
add 1 $counter &counter
|
||||
inequal 10 $counter &out
|
||||
stdout "Condition is"
|
||||
stdlnout $out
|
||||
if $out %jumpback
|
||||
stdlnout "Finished"
|
||||
return true
|
||||
endfun
|
||||
|
||||
call !jumpy &tmp
|
||||
|
||||
stdlnout "I called a function"
|
@@ -1,7 +1,9 @@
|
||||
@begin
|
||||
stdout "Do you like cheese? "
|
||||
stdin &userin
|
||||
equal $userin "yes" &condition
|
||||
if $condition %7
|
||||
if $condition %end
|
||||
stdlnout "That is sad"
|
||||
jump %1
|
||||
jump %begin
|
||||
@end
|
||||
stdlnout "Awesome! I do too!"
|
||||
|
13
tests/lists.grnd
Normal file
13
tests/lists.grnd
Normal file
@@ -0,0 +1,13 @@
|
||||
# A cool list
|
||||
setlist *favWords "hello" "there" "general" "kenobi"
|
||||
|
||||
set &count 0
|
||||
set &passedThrough true
|
||||
|
||||
@jmpbck
|
||||
getlistat *favWords $count &tmp
|
||||
stdlnout $tmp
|
||||
add $count 1 &count
|
||||
getlistsize *favWords &tmp2
|
||||
inequal $count $tmp2 &tmp3
|
||||
if $tmp3 %jmpbck
|
10
tests/typeconvs.grnd
Normal file
10
tests/typeconvs.grnd
Normal file
@@ -0,0 +1,10 @@
|
||||
stod "3.14" &out
|
||||
stdlnout $out
|
||||
|
||||
stoi "732" &out
|
||||
add 1 $out &out
|
||||
stdlnout $out
|
||||
|
||||
tostring 3.14 &out
|
||||
add $out " is a number of sorts" &out
|
||||
stdlnout $out
|
3
tests/use/library.grnd
Normal file
3
tests/use/library.grnd
Normal file
@@ -0,0 +1,3 @@
|
||||
fun -string !dingus
|
||||
return "Hello from the library"
|
||||
endfun
|
5
tests/use/use.grnd
Normal file
5
tests/use/use.grnd
Normal file
@@ -0,0 +1,5 @@
|
||||
use "library"
|
||||
|
||||
call !dingus &var
|
||||
|
||||
stdlnout $var
|
Reference in New Issue
Block a user