Skip to content

Commit

Permalink
Added separate Name type for variable handling
Browse files Browse the repository at this point in the history
  • Loading branch information
stuin committed Sep 22, 2023
1 parent e168730 commit 15cda09
Show file tree
Hide file tree
Showing 8 changed files with 226 additions and 176 deletions.
54 changes: 23 additions & 31 deletions docs/Basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,63 +25,55 @@ Lists can be created using a few different functions, but curly braces can also
#This is a comment.
```

This will not be evaluated as a function, just stored as a list.
In the same vein, quotation marks can be used to define strings, though any single word can be used as a string as well.
This will not be evaluated as a Function, but will instead be stored directly as a List.
Quotation marks can be used to define Strings.

```
string
"string"
```
These are equivalent.
```
lots of words
"lots of words"
```
These are not, as the first one will only include the first word.
Finally, if a string is the same as an existing function or variable, a colon can be used to denote the literal string.
```
:Set -> Set
Set -> <func>
:: -> :
```
A single word without quotes will default to a Name, but if there is no defined value it can usually be used as a String.
A single letter in quotes will become a Char.

## Argument folding
In any case where the very last argument that a function asks for is a list, the function can accept that list in two different ways. Either a normal list can be provided, or all objects in the list can be provided directly as arguments.
You may have noticed that a normal mathmatical operator can accept more than just two arguments. In fact, all the basic mathmatical operators effectivly have the builtin functionality of foldl.
In any case where the very last argument that a function asks for is a List, the function can accept that List in two different ways. Either a normal List can be provided, or all objects in the List can be provided directly as arguments.
You may have noticed that a normal mathmatical operator can accept more than just two arguments. In fact, all the basic mathmatical operators effectivly have the built-in functionality of foldl.
```
(+ 1 2 3 4 5)
(+ {1 2 3 4 5})
(+ (+ {1 2 3}) (+ 4 5))
(+ (+ 1 2) (+ 3 (+ 4 5)))
```
All these are equivalent.
It is important to note that any time there is only one argument in these cases, it is assumed to be a list. It may be required to put a string inside curly braces if it is the only value.
It is important to note that any time there is only one argument in these cases, it is assumed to be a list. It may be required to put a String inside curly braces if it is the only value.

## Type conversion
All objects are stored as c++ structures with specific types, but converting between types is done automatically and dynamically. Each row shows what a type can be converted to.

Type |Stored |Expr |List |Bool |Number |Char |String |Function |
---- |---- |---- |---- |---- |---- |---- |---- |---- |
Expr |vector |Yes |Yes |No |No |No |Append |No |
List |vector |Yes |Yes |No |No |No |Append |Yes |
Bool |char |No |Single |Yes |Yes |Value |Yes |No |
Number |int |No |Single |Yes |Yes |Value |Yes |No |
Char |char |No |Single |Value |Value |Yes |Yes |No |
String |string |No |Chars |Yes? |Yes? |Yes? |Yes |No |
Function|function|No |No |No |No |No |<:func>|Yes |
Type |Stored |Expr |Name |List |Bool |Number |Char |String |Function |
---- |---- |---- |---- |---- |---- |------ |---- |------ |-------- |
Expr |vector |Yes |No |Yes |No |No |No |Append |No |
Name |string |No |Yes |Chars |Yes? |Yes? |Yes? |Yes |No |
List |vector |Yes |Append |Yes |No |No |No |Append |Yes |
Bool |char |No |No |Single |Yes |Yes |Value |Yes |No |
Number |int |No |No |Single |Yes |Yes |Value |Yes |No |
Char |char |No |Yes |Single |Value |Value |Yes |Yes |No |
String |string |No |Yes |Chars |Yes? |Yes? |Yes? |Yes |No |
Function|function|No |No |No |No |No |No |<func> |Yes |

## Variables
Anything can be stored in a variable, including all of the above types. Variables are dynamically typed, dynamically scoped, and case sensitive.
Any time a string or char is evaluated, the system will check for an existing variable under that name, and return that instead if found. All builtin functions are provided through variables as well.
To set a variable, the Set function can be used, followed by a name and a value.

Names and Strings function very similar to each other, but Names will attempt to resolve as a variable before anything else.

To set a variable, the Set function can be used, followed by a Name and a value.
```
(Set x 3)
```
This will return and give x the value 3 in the current scope. Using the set command, all variables are immutable, and cannot be changed. However, variables can be reassigned by replacing Set with Mutate.
This will give x the value 3 in the current scope and additionally will return the value 3. Using the Set command, all variables are immutable, and cannot be changed. However, variables can be reassigned by replacing Set with Mutate.

## Constants
There are a few useful system constants,
they should all be pretty obvious.
There are a few useful system constants.
```
true
false
Expand Down
17 changes: 10 additions & 7 deletions docs/Functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,27 @@ Not |Bool |Bool |Not gate |
== |Bool |\[Any\] |Is equal |
\!= |Bool |\[Any\] |Is not equal |
Type |String |Any |Returns string representing type of object |
Join |String |\[String\],<String>|Concat strings together with delimeter |
Force |Any |Name,Any |Convert second to named type |
JoinD |String |String,\[String\] |Concat strings together with delimeter |
Join |String |\[String\],<String>|Join but reversed arguments (deprecated) |
Print |String |string |Print to stdout and return |
Append |\[Any\]|\[\[Any\]\] |Append lists together |
Seq |\[Num\]|Num,Num |List numbers from first to second |
Remove |\[Any\]|Any,\[Any\] |Remove all that equal first from list |
Tail |\[Any\]|\[Any\] |Remove first element from list |
Clone |\[Any\]|Num,\[Any\] |Copy entire list and append it n times |
Reverse |\[Any\]|\[Any\] |Reverse entire list |
If |Any |Bool,Any,<Any> |If true, second, else third/0 |
If |Any |Bool,Any,<Any> |If true, second, else third or 0 |
Step |Any |\[Any\] |Evaluate all elements, return last one |
Switch |Any |\[\[Bool,Any\]\] |Return end of the first list to start with true|
Get |Any |Num,\[Any\] |Return nth element in list |
Length |Num |\[Any\] |Calculate length of list |
Get-Max |Num |\[Max\] |Get max element in list |
Map |\[Any\]|String,\[Any\],Any |For each element in list, evaluate third |
MapI |\[Any\]|String,String,\[Any\],Any |Map but with a second index variable |
Max |Num |\[Max\] |Get max element in list |
Map |\[Any\]|Name,\[Any\],Any |For each element in list, evaluate third |
MapI |\[Any\]|Name,Name,\[Any\],Any |Map but with a second index variable |
Repeat |Num |Bool |Counts how many times the bool is true |
Set |Any |String,Any |Set value of string to third, return third |
Mutate |Any |String,Any |Set but not pure/safe |
Set |Any |Name,Any |Set value of Name to third, return third |
Mutate |Any |Name,Any |Set but not pure/safe |


[Basic Structure](https://github.com/stuin/Solisp/blob/master/docs/Basics.md)
46 changes: 32 additions & 14 deletions docs/test.solisp
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,58 @@
(* 5 1)
(/ 20 4)
(% 15 10)
) Passed Fail)
) "Passed" "Fail")

#Building and summing up lists
(If (< (+ (Set list (Seq 1 5))) 20) #{+ 1 2 3 4 5}
Passed Fail)
"Passed" "Fail")

#Mapping loops and product of a list
(If (* (Map x list (!= x 0)))
Passed Fail)
"Passed" "Fail")

#Alternate map function
(If (* (MapI x i list (> x i)))
Passed Fail)
"Passed" "Fail")

#Manual types
(If (== (Force Number "*") 42)
"Passed" "Fail")

#General list modifying
(Join (Remove , (Join (Reverse "e,d" s s a P) ,)))
(Remove "," (JoinD "," (Reverse "e,d" "s" "s" "a" "P")))

#Step
(Step (Set start Pass) (Join {start ed}))
(Step (Set start "Pass") {start "ed"})

#Switch statement
(Switch
{(== 5 3) Fail1}
{(> 6 10) Fail2}
{(!= 3 1) Passed}
{(< 3 0) Fail3}
{True Fail4}
{(== 5 3) "Fail1"}
{(> 6 10) "Fail2"}
{(!= 3 1) "Passed"}
{(< 3 0) "Fail3"}
{True "Fail4"}
)

#Name vs String
(Step
(Set Fail "Pass")
(Set e "Fail")
{Fail "e" d}
)

#Constructed Names
(Step
(Set "F1" "Pass")
(Set {"F" (+ 1 1)} "ed")
{(Force Name "F1") (Force Name {"F" 2})}
)

#Basic user-defined function
(If (== (
{{x y} (+ x y)}
2 3) 5)
Passed Fail)
"Passed" "Fail")

#Succesfull recursive function
(If (== ((Set fact {
Expand All @@ -51,11 +69,11 @@ Passed Fail)
0
)
}) 4) 10)
Passed Fail)
"Passed" "Fail")

#Weird formatting test
(If#Testing
1(Join {Pass ed})"Fail"
1{"Pass" "ed"}"Fail"
)

args
46 changes: 35 additions & 11 deletions src/library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,13 @@ void Enviroment::build_library() {
force_eval[EXPR] = [](Enviroment *env, cell const &c) {
return c;
};
type_name[NAME] = "Name";
force_eval[NAME] = [](Enviroment *env, cell const &c) {
return cell(env->name_eval(c), NAME);
};
type_name[STRING] = "String";
force_eval[STRING] = [](Enviroment *env, cell const &c) {
return cell(env->str_eval(c, false), STRING);
return cell(env->str_eval(c), STRING);
};
type_name[BOOL] = "Boolean";
force_eval[BOOL] = [](Enviroment *env, cell const &c) {
Expand All @@ -64,7 +68,6 @@ void Enviroment::build_library() {
set("true", cell((char)1, BOOL));
set("false", cell((char)0, BOOL));
set("newline", cell("\n"));
set("\\n", cell("\n"));

//Basic arithmatic
set("+", arithmetic(std::plus<int>()));
Expand Down Expand Up @@ -110,8 +113,29 @@ void Enviroment::build_library() {
set("Type", cell([](Enviroment *env, marker pos, marker end) {
return env->type_name[(int)env->eval(*pos).type];
}));
set("Force", cell([](Enviroment *env, marker pos, marker end) {
string type = env->name_eval(*pos++);

for(int i = 0; i < MAX_TYPE; i++)
if(env->type_name[i] == type)
return env->force_eval[i](env, *pos++);
throw std::domain_error("Type " + type + " not found");
}));

//String functions
set("JoinD", cell([](Enviroment *env, marker pos, marker end) {
string delim = env->str_eval(*pos++);
LISTREMAINS;
string output;

//Special string functions
//Perform actual appending
while(pos != end)
output += env->str_eval(*pos++) + delim;

DONE;
return output;
}));
//Old join function, deprecated because of argument ordering
set("Join", cell([](Enviroment *env, marker pos, marker end) {
sexpr array = env->list_eval(*pos++);
string output;
Expand All @@ -123,13 +147,13 @@ void Enviroment::build_library() {

//Perform actual appending
for(cell s : array)
output += env->str_eval(s, false) + delim;
output += env->str_eval(s) + delim;

DONE;
return output;
}));
set("Print", cell([](Enviroment *env, marker pos, marker end) {
string s = env->str_print(*pos++);
string s = env->str_eval(*pos++);
std::cout << s;
DONE;
return cell(s);
Expand Down Expand Up @@ -269,7 +293,7 @@ void Enviroment::build_library() {

return cell(size);
}));
set("Get-Max", cell([](Enviroment *env, marker pos, marker end) {
set("Max", cell([](Enviroment *env, marker pos, marker end) {
LISTREMAINS;
int max = env->num_eval(*pos++);

Expand All @@ -285,7 +309,7 @@ void Enviroment::build_library() {

//High level functions
set("Map", cell([](Enviroment *env, marker pos, marker end) {
string var = env->str_print(*pos++, true);
string var = env->name_eval(*pos++);
sexpr array = env->list_eval(*pos++);
sexpr output;
env->shift_env(true);
Expand All @@ -302,8 +326,8 @@ void Enviroment::build_library() {
return cell(output, LIST);
}));
set("MapI", cell([](Enviroment *env, marker pos, marker end) {
string var = env->str_print(*pos++, true);
string index = env->str_eval(*pos++);
string var = env->name_eval(*pos++);
string index = env->name_eval(*pos++);
sexpr array = env->list_eval(*pos++);
sexpr output;
env->shift_env(true);
Expand Down Expand Up @@ -335,7 +359,7 @@ void Enviroment::build_library() {

//Variable management
set("Set", cell([](Enviroment *env, marker pos, marker end) {
string name = env->str_print(*pos++);
string name = env->name_eval(*pos++);

//Check for existing value
if(env->get(name) != NULL)
Expand All @@ -346,7 +370,7 @@ void Enviroment::build_library() {
return output;
}));
set("Mutate", cell([](Enviroment *env, marker pos, marker end) {
string name = env->str_print(*pos++);
string name = env->name_eval(*pos++);
cell output = env->set(name, *pos++);

DONE;
Expand Down
Loading

0 comments on commit 15cda09

Please sign in to comment.