initial project setup

This commit is contained in:
VaclavT 2021-02-09 13:53:35 +01:00
commit d64570bf21
12 changed files with 2152 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build

20
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,20 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(lldb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/ml",
"args": ["-f", "${workspaceFolder}/debug.lisp"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"console": "externalTerminal",
"MIMode": "lldb"
}
]
}

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools"
}

25
CMakeLists.txt Normal file
View File

@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.0.0)
project(ml VERSION 0.1.0)
# set(CMAKE_CXX_STANDARD 17)
# set(CMAKE_CXX_STANDARD_REQUIRED ON)
# set(CMAKE_CXX_EXTENSIONS OFF)
# set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14")
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include_directories(${CMAKE_SOURCE_DIR}/stdlib ${CMAKE_SOURCE_DIR} )
project(ml)
set(PROJECT_NAME ml)
set(SOURCE
ml.cpp
stdlib/csvparser.cpp)
add_executable(${PROJECT_NAME} ${SOURCE})
target_link_libraries(${PROJECT_NAME} stdc++ m)

24
Readme.md Normal file
View File

@ -0,0 +1,24 @@
### TODO
#### Functionality
- readline
- cvs read
- url read
- json
- printf
- env
- support for including lib
- date support
#### Performance
- push_back - repeately without reserving size
### Example of use
```
time ./ml -c '(include "../example.lisp") (print (fact 1000))'
```

3
debug.lisp Normal file
View File

@ -0,0 +1,3 @@
(print "Debug starts")
(read-file "tmp/data.csv")
(print "Debug ends")

151
doc/Doc.md Normal file
View File

@ -0,0 +1,151 @@
# wisp
A light lisp written in C++
![Wisp](./wisp.png)
## Why write a lisp?
Lisp is one of those niche, beautiful languages that people only really use to either
1. Write a lisp interpreter
2. Show off how "code is data!!!"
_So why add to the list of infinite lisp interpreters?_
The answer is simple: _**I'm bored out of my mind in quarantine.**_ If you were looking to find out why _this particular_ lisp is special, you're fresh out of luck.
## Syntax and Special Forms
Like every other lisp, this language uses s-expressions for code syntax and data syntax. So, for example, the s-expression `(print 5)` is both a valid code snippet, and a valid list containing the items `print` and `5`.
When the data `(print 5)` is evaluated by the interpreter, it evaluates `print` and `5`, and then applies `print` to `5`.
Here's the result.
```lisp
>>> (print 5)
5
=> 5
```
That's super cool! But what if we want to define our own functions? _We can use the builtin function `defun`!_
```lisp
; define a function `fact` that takes an argument `n`
(defun fact (n)
(if (<= n 1)
1
(* n (fact (- n 1)))
))
```
Thats awesome! But did you notice anything different about the `defun` function? _It doesn't evaluate its arguments._ If the atom `fact` were evaluated, it would throw an error like so:
```lisp
>>> fact
error: the expression `fact` failed in scope { } with message "atom not defined"
```
This is known as a special form, where certain functions "quote" their arguments. We can quote things ourselves too, but the language _automatically_ quotes arguments to special forms itself.
If you want to "quote" a value yourself, you can do it like this.
```lisp
; quote the s-expression (1 2 3) so it's not evaluated
>>> (print '(1 2 3))
(1 2 3)
=> (1 2 3)
```
As you can see, quote negates an evaluation. For example, whenever the expression `''a` is evaluated, it becomes `'a`. This can be useful for when you want to write long lists of data or variable names without wanting to evaluate them as code.
|Special Form|Argument Evaluations|Purpose|
|:-|-|-|
|`(if cond a b)`|`if` only evaluates its `cond` argument. If `cond` is truthy (non-zero), then `a` is evaluated. Otherwise, `b` is evaluated.|This special form is the main method of control flow.|
|`(do a b c ...)`|`do` takes a list of s-expressions and evaluates them in the order they were given (in the current scope), and then returns the result of the last s-expression.|This special form allows lambda functions to have multi-step bodies.|
|`(scope a b c ...)`|`scope` takes a list of s-expressions and evaluates them in the order they were given _in a new scope_, and then returns the result of the last s-expression.|This special form allows the user to evaluate blocks of code in new scopes.|
|`(defun name params body)`|`defun` evaluates none of its arguments.|This special form allows the user to conveniently define functions.|
|`(define name value)`|`define` evaluates the `value` argument, which is then assigned to `name` in the current scope.|This special form allows the user to bind atoms to values in a scope.|
|`(lambda params body)`|`lambda` evaluates none of its arguments.|This special form allows the user to define anonymous functions.|
|`(quote x)`|`quote` evaluates none of its arguments.|This is equivalent to the `'expr` syntactic sugar.|
|`(for x list ...)`|`for` evaluates only its list argument.|`for` iterates through the list storing each element in `x`, and then evaluating all of the rest of the values in the `for` body. It then returns the last value evaluated.|
|`(while cond ...)`|`while` evaluates only its cond argument.|`while` evaluates its condition expression every iteration before running. If it is true, it continues to evaluate every expression in the `while` body. It then returns the last value evaluated.|
## Examples
Here are some example math-y functions to wrap your head around.
```lisp
; quicksort
(defun qs (l)
(if (<= (len l) 1)
l
(do
(define pivot (first l))
(+
(qs (filter (lambda (n) (> pivot n)) l))
(list pivot)
(qs (tail (filter (lambda (n) (<= pivot n)) l)))
))
))
; decrement a number
(defun dec (n) (- n 1))
; increment a number
(defun inc (n) (+ n 1))
; not a bool
(defun not (x) (if x 0 1))
; negate a number
(defun neg (n) (- 0 n))
; is a number positive?
(defun is-pos? (n) (> n 0))
; is a number negative?
(defun is-neg? (n) (< n 0))
```
## Usage
Using and compiling wisp
#### Dependencies
Compile with your C++ compiler of choice. This is compatible with all standard versions of C++ since ANSI C++.
```bash
$ git clone https://github.com/adam-mcdaniel/wisp
$ cd wisp
$ g++ wisp.cpp -o wisp
```
#### Using the binary
Run wisp in interactive mode:
```bash
$ ./wisp
>>> (print "Hello world!")
Hello world!
=> "Hello world!"
```
Interpret a file:
```bash
$ ./wisp -f "examples/hello_world.lisp"
Hello world!
```
Interpret from command line argument:
```bash
$ ./wisp -c '(print "Hello world!")'
Hello world!
```
source from :
https://github.com/adam-mcdaniel/wisp

1795
ml.cpp Normal file

File diff suppressed because it is too large Load Diff

68
stdlib/csvparser.cpp Normal file
View File

@ -0,0 +1,68 @@
#include "csvparser.h"
CsvParser::CsvParser(bool skip_hdr, char field_sep, char quote_ch, char line_sep, char line_sep2) {
skip_header = skip_hdr;
field_separator = field_sep;
quote_character = quote_ch;
line_separator = line_sep;
line_separator2 = line_sep2;
header_skiped = false;
}
void CsvParser::parseCSV(const std::string &csvSource, std::vector< std::vector<std::string> > &lines) {
bool inQuote(false);
bool newLine(false);
std::string field;
lines.clear();
std::vector<std::string> line;
std::string::const_iterator aChar = csvSource.begin();
while (aChar != csvSource.end()) {
if (*aChar == quote_character) {
newLine = false;
inQuote = !inQuote;
} else if (*aChar == field_separator) {
newLine = false;
if (inQuote == true) {
field += *aChar;
} else {
line.push_back(field);
field.clear();
}
} else if (*aChar == line_separator || *aChar == line_separator2) {
if (inQuote == true) {
field += *aChar;
} else {
if (newLine == false) {
line.push_back(field);
addLine(line, lines);
field.clear();
line.clear();
newLine = true;
}
}
} else {
newLine = false;
field.push_back(*aChar);
}
aChar++;
}
if (field.size())
line.push_back(field);
addLine(line, lines);
}
void CsvParser::addLine(const std::vector<std::string> &line, std::vector< std::vector<std::string> > &lines) {
if (skip_header && !header_skiped) {
header_skiped = true;
} else {
if (line.size())
lines.push_back(line);
}
}

23
stdlib/csvparser.h Normal file
View File

@ -0,0 +1,23 @@
#include <string>
#include <vector>
class CsvParser {
private:
char field_separator;
char line_separator;
char line_separator2;
char quote_character;
bool skip_header;
bool header_skiped;
public:
CsvParser(bool skip_hdr = false, char field_sep = ',', char quote_ch = '"', char line_sep = '\r', char line_sep2 = '\n');
void parseCSV(const std::string &csvSource, std::vector< std::vector<std::string> > &lines);
private:
void addLine(const std::vector<std::string> &line, std::vector< std::vector<std::string> > &lines);
};

3
tmp/data.csv Normal file
View File

@ -0,0 +1,3 @@
Ticker,Price
FDX,257.3
C,59.85
1 Ticker Price
2 FDX 257.3
3 C 59.85

36
tmp/example.lisp Normal file
View File

@ -0,0 +1,36 @@
; quicksort
(defun qs (l)
(if (<= (len l) 1)
l
(do
(define pivot (first l))
(+
(qs (filter (lambda (n) (> pivot n)) l))
(list pivot)
(qs (tail (filter (lambda (n) (<= pivot n)) l)))
))
))
; decrement a number
(defun dec (n) (- n 1))
; increment a number
(defun inc (n) (+ n 1))
; not a bool
(defun not (x) (if x 0 1))
; negate a number
(defun neg (n) (- 0 n))
; is a number positive?
(defun is-pos? (n) (> n 0))
; is a number negative?
(defun is-neg? (n) (< n 0))
; define a function `fact` that takes an argument `n`
(defun fact (n)
(if (<= n 1)
1
(* n (fact (- n 1)))
))
(print "example.lisp loaded")