added project files

This commit is contained in:
Ludwig Lehnert 2024-02-24 21:34:06 +01:00
commit 9655c05697
23 changed files with 521 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build/

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

@ -0,0 +1,76 @@
{
"[yacc]": {
"problems.decorations.enabled": false,
},
"files.associations": {
"*.embeddedhtml": "html",
"any": "cpp",
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"charconv": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"list": "cpp",
"map": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"format": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"semaphore": "cpp",
"span": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stdfloat": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"thread": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp",
"valarray": "cpp",
"variant": "cpp"
},
}

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# plsm
Mainly functional general purpose programming language

1
compiler/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.gen.*

28
compiler/CMakeLists.txt Normal file
View File

@ -0,0 +1,28 @@
cmake_minimum_required(VERSION 3.25)
project(plasmatum)
set(CMAKE_CXX_STANDARD 23)
set(SOURCE_DIR ${CMAKE_SOURCE_DIR}/src)
set(INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include)
find_package(FLEX REQUIRED)
find_package(BISON REQUIRED)
BISON_TARGET(parser
${CMAKE_SOURCE_DIR}/parser.yy
${SOURCE_DIR}/parser.gen.cpp
DEFINES_FILE ${INCLUDE_DIR}/parser.gen.h)
FLEX_TARGET(lexer
${CMAKE_SOURCE_DIR}/lexer.ll
${SOURCE_DIR}/lexer.gen.cpp)
ADD_FLEX_BISON_DEPENDENCY(lexer parser)
file(GLOB_RECURSE sources ${SOURCE_DIR}/*.cpp)
set(sources ${sources} ${FLEX_lexer_OUTPUTS})
set(sources ${sources} ${BISON_parser_OUTPUT_SOURCE})
include_directories(${CMAKE_SOURCE_DIR}/include)
add_executable(plsm ${sources})

49
compiler/include/AST.h Normal file
View File

@ -0,0 +1,49 @@
#pragma once
#include <string>
class Expr;
class ASTNode
{
};
class Stmt : public ASTNode
{
};
class Decl : public Stmt
{
public:
Decl(const std::string &identifier, const Expr *value)
: identifier(identifier), value(value) {}
const std::string identifier;
const Expr *value;
};
class Expr : public ASTNode
{
};
class IntValue : public Expr
{
public:
const long value;
IntValue(const long value) : value(value) {}
};
class FloatValue : public Expr
{
public:
const double value;
FloatValue(const double value) : value(value) {}
};
class Function : public Expr
{
};
class List : public Expr
{
};

View File

@ -0,0 +1,22 @@
#pragma once
#include <stdexcept>
#include "AST.h"
template <typename T>
class ASTVisitor
{
virtual T visit(const ASTNode *node)
{
if (IntValue *cnode = dynamic_cast<IntValue *>(node))
return visitIntValue(cnode);
else if (FloatValue *cnode = dynamic_cast<FloatValue *>(node))
return visitFloatValue(cnode);
throw std::logic_error("not implemented");
}
virtual T visitIntValue(const IntValue *node);
virtual T visitFloatValue(const IntValue *node);
};

View File

@ -0,0 +1,23 @@
#pragma once
#include <string>
#include "AST.h"
#include "parser.gen.h"
class ParserDriver
{
public:
ParserDriver() {}
int parse(const std::string &input);
void startLexer();
void stopLexer();
std::string file;
yy::location location;
};
#define YY_DECL yy::parser::symbol_type yylex(ParserDriver &driver)
YY_DECL;

57
compiler/lexer.ll Normal file
View File

@ -0,0 +1,57 @@
%{
#include "parser.gen.h"
#include "ParserDriver.h"
#define yyterminate() yy::parser::make_END(yy::location())
#define _token(token) yy::parser::make_##token(driver.location)
%}
%option noyywrap nounput noinput batch debug
digit [0-9]
bindigit [0-1]
octdigit [0-7]
hexdigit [0-9a-fA-F]
letter [a-zA-Z]
whitespace [ \n\t\r\v]+
%%
"0b"{bindigit}+ { return yy::parser::make_INT(std::strtol(yytext, NULL, 2), driver.location); }
"0o"{octdigit}+ { return yy::parser::make_INT(std::strtol(yytext, NULL, 8), driver.location); }
"0x"{hexdigit}+ { return yy::parser::make_INT(std::strtol(yytext, NULL, 16), driver.location); }
{digit}+ { return yy::parser::make_INT(std::strtol(yytext, NULL, 10), driver.location); }
{digit}*"."{digit}+ { return yy::parser::make_FLOAT(std::strtod(yytext, NULL), driver.location); }
// TODO: operator '==' won't work this way
"->" { return _token(R_ARR); }
"<-" { return _token(L_ARR); }
";" { return _token(SEMI); }
"=" { return _token(EQUALS); }
("+"|"-"|"*"|"/"|"%"|"!"|"&"|"$"|"§"|"|"|"="|"<"|">"|"?"|"~"|"#"|":"|"^"|"\\")+ { return _token(OPERATOR); }
"fn" { return _token(FN); }
"unop" { return _token(UNOP); }
"binop" { return _token(BINOP); }
"val" { return _token(VAL); }
"import" { return _token(IMPORT); }
"declare" { return _token(DECLARE); }
{letter}({digit}|{letter})* { return yy::parser::make_IDENTIFIER(yytext, driver.location); }
{whitespace} { ; }
%%
void ParserDriver::startLexer() {
yy_scan_string(this->file.data());
}
void ParserDriver::stopLexer() {}

106
compiler/parser.yy Normal file
View File

@ -0,0 +1,106 @@
%require "3.8"
%language "c++"
%header
%define api.token.raw
%define api.value.type variant
%define api.token.constructor
%define api.token.prefix {TOK_}
%define parse.assert
%define parse.trace
%define parse.error detailed
%define parse.lac full
%locations
%define api.location.file "../include/location.gen.h"
%define api.location.include {"location.gen.h"}
%code requires {
#include "AST.h"
class ParserDriver;
}
%lex-param { ParserDriver &driver }
%parse-param { ParserDriver &driver }
%code {
#include "ParserDriver.h"
}
%token <long> INT "integer literal"
%token <double> FLOAT "float literal"
%token <std::string> OPERATOR "operator";
%token <std::string> IDENTIFIER "identifier"
%token L_ARR "<-"
%token R_ARR "->"
%token EQUALS "="
%token SEMI ";"
%token
FN "fn"
UNOP "unop"
BINOP "binop"
VAL "val"
IMPORT "import"
DECLARE "declare"
;
%token END 0 "end of file"
%type <std::vector<Stmt *>> stmts;
%type <Stmt *> stmt;
%type <Decl *> decl;
%type <Expr *> expr;
%type <Value *> literal;
%type <std::string> operator;
%type <std::string> identifier;
%type <std::string> keyword;
%%
module: stmts;
stmts: stmt { $$ = std::vector<Stmt *>(); $$.push_back($1); }
| stmts stmt { $1.push_back($2); $$ = std::move($1); }
;
stmt: decl { $$ = $1; }
;
decl: VAL identifier "=" expr ";" { $$ = new Decl($2, $4); }
;
expr: literal { $$ = $1; }
;
literal: INT { $$ = new IntValue($1); }
| FLOAT { $$ = new FloatValue($1); }
;
operator: L_ARR { $$ = $1; }
| R_ARR { $$ = $1; }
| EQUALS { $$ = $1; }
| OPERATOR { $$ = $1; }
;
identifier: keyword { $$ = $1; }
| IDENTIFIER { $$ = $1; }
;
keyword: FN { $$ = $1; }
| UNOP { $$ = $1; }
| BINOP { $$ = $1; }
| IMPORT { $$ = $1; }
| DECLARE { $$ = $1; }
;
%%
void yy::parser::error (const location_type& l, const std::string& m) {
std::cerr << l << ": " << m << '\n';
}

View File

@ -0,0 +1,14 @@
#include "ParserDriver.h"
int ParserDriver::parse(const std::string &input)
{
file = input;
location.initialize(&file);
startLexer();
yy::parser parse(*this);
int res = parse();
stopLexer();
return res;
}

5
compiler/src/main.cpp Normal file
View File

@ -0,0 +1,5 @@
#include <string>
int main()
{
}

30
examples/stdlib.plsm Normal file
View File

@ -0,0 +1,30 @@
type Bool = class {
declare unop ! -> Bool;
declare binop &&(b Bool) -> Bool;
declare binop ||(b Bool) -> Bool;
};
type Int = class {
declare unop + -> Int;
declare unop - -> Int;
declare binop ==(b Int) -> Bool;
declare binop !=(b Int) -> Bool;
declare binop >(b Int) -> Bool;
declare binop <(b Int) -> Bool;
declare binop >=(b Int) -> Bool;
declare binop <=(b Int) -> Bool;
declare binop +(b Int) -> Int;
declare binop -(b Int) -> Int;
declare binop *(b Int) -> Int;
declare binop /(b Int) -> Int;
declare binop %(b Int) -> Int;
declare fn str() -> String;
};
type String = class (data List[Char]) {
}

9
lib/CMakeLists.txt Normal file
View File

@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.25)
project(libplsm C)
set(CMAKE_C_STANDARD 11)
file(GLOB_RECURSE sources ${CMAKE_SOURCE_DIR}/src/*.c)
include_directories(${CMAKE_SOURCE_DIR}/include)
add_library(libplsm SHARED ${sources})

6
lib/include/function.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
typedef struct
{
} function_t;

16
lib/include/list.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include "type.h"
#include "value.h"
typedef struct
{
value_t *value;
list_node_t *next;
} list_node_t;
typedef struct
{
type_t *type;
list_node_t *head;
} list_t;

19
lib/include/macros.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include <stdlib.h>
#include <stdio.h>
#define DIE \
{ \
exit(EXIT_FAILURE); \
}
#define DIE_ERRNO(action) \
{ \
perror(action); \
DIE; \
}
#define MODINIT(module) void plsmmod_##module##_init()
#define LIB(name) plsmlib_##name

14
lib/include/type.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#include "macros.h"
typedef struct type_t type_t;
typedef struct type_t
{
type_t *base;
int opaque;
char *name;
} type_t;
type_t *LIB(makeType)(type_t *base, int opaque, char *name);

9
lib/include/value.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#include "type.h"
typedef struct
{
type_t *type;
void *value;
} value_t;

1
lib/src/function.c Normal file
View File

@ -0,0 +1 @@
#include "function.h"

5
lib/src/module.c Normal file
View File

@ -0,0 +1,5 @@
#include "macros.h"
MODINIT(stdlib)
{
}

16
lib/src/type.c Normal file
View File

@ -0,0 +1,16 @@
#include "type.h"
#include <stdlib.h>
type_t *LIB(makeType)(type_t *base, int opaque, char *name)
{
type_t *type = malloc(sizeof(type_t));
if (!type)
DIE_ERRNO("malloc");
type->base = base;
type->opaque = opaque;
type->name = name;
return type;
}

12
lib/src/types.c Normal file
View File

@ -0,0 +1,12 @@
#include "type.h"
type_t *LIB(typeAny), *LIB(typeNum), *LIB(typeInt), *LIB(typeFloat);
void LIB(initTypes)()
{
LIB(typeAny) = LIB(makeType)(NULL, "Any");
LIB(typeNum) = LIB(makeType)(LIB(typeAny), "Num");
LIB(typeInt) = LIB(makeType)(LIB(typeNum), "Int");
LIB(typeFloat) = LIB(makeType)(LIB(typeNum), "Float");
}