added project files
This commit is contained in:
commit
9655c05697
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
build/
|
76
.vscode/settings.json
vendored
Normal file
76
.vscode/settings.json
vendored
Normal 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
2
README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# plsm
|
||||||
|
Mainly functional general purpose programming language
|
1
compiler/.gitignore
vendored
Normal file
1
compiler/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.gen.*
|
28
compiler/CMakeLists.txt
Normal file
28
compiler/CMakeLists.txt
Normal 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
49
compiler/include/AST.h
Normal 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
|
||||||
|
{
|
||||||
|
};
|
22
compiler/include/ASTVisitor.h
Normal file
22
compiler/include/ASTVisitor.h
Normal 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);
|
||||||
|
};
|
23
compiler/include/ParserDriver.h
Normal file
23
compiler/include/ParserDriver.h
Normal 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
57
compiler/lexer.ll
Normal 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
106
compiler/parser.yy
Normal 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';
|
||||||
|
}
|
14
compiler/src/ParserDriver.cpp
Normal file
14
compiler/src/ParserDriver.cpp
Normal 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
5
compiler/src/main.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include <string>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
}
|
30
examples/stdlib.plsm
Normal file
30
examples/stdlib.plsm
Normal 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
9
lib/CMakeLists.txt
Normal 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
6
lib/include/function.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
|
||||||
|
} function_t;
|
16
lib/include/list.h
Normal file
16
lib/include/list.h
Normal 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
19
lib/include/macros.h
Normal 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
14
lib/include/type.h
Normal 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
9
lib/include/value.h
Normal 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
1
lib/src/function.c
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "function.h"
|
5
lib/src/module.c
Normal file
5
lib/src/module.c
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include "macros.h"
|
||||||
|
|
||||||
|
MODINIT(stdlib)
|
||||||
|
{
|
||||||
|
}
|
16
lib/src/type.c
Normal file
16
lib/src/type.c
Normal 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
12
lib/src/types.c
Normal 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");
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user