mirror of
https://github.com/CPunch/Cosmo.git
synced 2025-07-14 22:50:16 +00:00
Compare commits
No commits in common. "c8cae0360484022117bbe7471745b1ba1583a355" and "7279623e24d60b3e6c8c152be809b65bbeabf8b6" have entirely different histories.
c8cae03604
...
7279623e24
14
README.md
14
README.md
@ -5,31 +5,31 @@ Cosmo is a portable scripting language loosely based off of Lua. Cosmo easily al
|
|||||||
|
|
||||||
```lua
|
```lua
|
||||||
proto Vector
|
proto Vector
|
||||||
func __init(self)
|
function __init(self)
|
||||||
self.vector = []
|
self.vector = []
|
||||||
self.x = 0
|
self.x = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
func __index(self, key)
|
function __index(self, key)
|
||||||
return self.vector[key]
|
return self.vector[key]
|
||||||
end
|
end
|
||||||
|
|
||||||
func push(self, val)
|
function push(self, val)
|
||||||
self.vector[self.x++] = val
|
self.vector[self.x++] = val
|
||||||
end
|
end
|
||||||
|
|
||||||
func pop(self)
|
function pop(self)
|
||||||
return self.vector[--self.x]
|
return self.vector[--self.x]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
let vector = Vector()
|
var vector = Vector()
|
||||||
|
|
||||||
for (let i = 0; i < 4; i++) do
|
for (var i = 0; i < 4; i++) do
|
||||||
vector:push(i)
|
vector:push(i)
|
||||||
end
|
end
|
||||||
|
|
||||||
for (let i = 0; i < 4; i++) do
|
for (var i = 0; i < 4; i++) do
|
||||||
print(vector:pop() .. " : " .. vector[i])
|
print(vector:pop() .. " : " .. vector[i])
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// just testing continues and breaks
|
// just testing continues and breaks
|
||||||
|
|
||||||
for (let x = 0; x < 700; x++) do
|
for (var x = 0; x < 700; x++) do
|
||||||
for (let i = 0; true; i++) do
|
for (var i = 0; true; i++) do
|
||||||
let str = i .. "." .. x
|
var str = i .. "." .. x
|
||||||
if (i == 998) then
|
if (i == 998) then
|
||||||
print(i .. " reached")
|
print(i .. " reached")
|
||||||
break // exits the loop
|
break // exits the loop
|
||||||
@ -13,9 +13,9 @@ for (let x = 0; x < 700; x++) do
|
|||||||
end
|
end
|
||||||
|
|
||||||
// same example as the for loop but done manually using a while loop
|
// same example as the for loop but done manually using a while loop
|
||||||
let i = 0
|
var i = 0
|
||||||
while true do
|
while true do
|
||||||
let str = i .. "." .. x
|
var str = i .. "." .. x
|
||||||
if (i++ == 998) then
|
if (i++ == 998) then
|
||||||
print("done")
|
print("done")
|
||||||
break
|
break
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
let strtable = []
|
var strtable = []
|
||||||
let strLen = 4 // length of all strings to generate
|
var strLen = 4 // length of all strings to generate
|
||||||
let AByte = "A":byte() // grabs the ascii value of 'A'
|
var AByte = "A":byte() // grabs the ascii value of 'A'
|
||||||
|
|
||||||
proto stringBuilder
|
proto stringBuilder
|
||||||
func __init(self, length)
|
function __init(self, length)
|
||||||
self.len = length
|
self.len = length
|
||||||
end
|
end
|
||||||
|
|
||||||
// we are the iterator object lol
|
// we are the iterator object lol
|
||||||
func __iter(self)
|
function __iter(self)
|
||||||
self.x = 0
|
self.x = 0
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
func __next(self)
|
function __next(self)
|
||||||
let x = self.x++
|
var x = self.x++
|
||||||
|
|
||||||
// if we've generated all the possible strings, return nil ending the loop
|
// if we've generated all the possible strings, return nil ending the loop
|
||||||
if x >= 26 ^ self.len then
|
if x >= 26 ^ self.len then
|
||||||
@ -22,8 +22,8 @@ proto stringBuilder
|
|||||||
end
|
end
|
||||||
|
|
||||||
// generate the string
|
// generate the string
|
||||||
let str = ""
|
var str = ""
|
||||||
for (let i = 0; i < self.len; i++) do
|
for (var i = 0; i < self.len; i++) do
|
||||||
str = string.char(AByte + (x % 26)) .. str
|
str = string.char(AByte + (x % 26)) .. str
|
||||||
|
|
||||||
x = math.floor(x / 26)
|
x = math.floor(x / 26)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
local func fib(num)
|
local function fib(num)
|
||||||
if num <= 1 then
|
if num <= 1 then
|
||||||
return num
|
return num
|
||||||
else
|
else
|
||||||
@ -6,6 +6,6 @@ local func fib(num)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for (let i = 1; i < 40; i++) do
|
for (var i = 1; i < 40; i++) do
|
||||||
print("The fib number of " .. i .. " is " .. fib(i))
|
print("The fib number of " .. i .. " is " .. fib(i))
|
||||||
end
|
end
|
@ -1,4 +1,4 @@
|
|||||||
let object = {
|
var object = {
|
||||||
__setter = [
|
__setter = [
|
||||||
"field1" = function(self, val)
|
"field1" = function(self, val)
|
||||||
print("setter for field1 called!")
|
print("setter for field1 called!")
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
proto Vector
|
proto Vector
|
||||||
func __init(self)
|
function __init(self)
|
||||||
self.vector = []
|
self.vector = []
|
||||||
self.x = 0
|
self.x = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
func push(self, val)
|
function push(self, val)
|
||||||
self.vector[self.x++] = val
|
self.vector[self.x++] = val
|
||||||
end
|
end
|
||||||
|
|
||||||
func pop(self)
|
function pop(self)
|
||||||
return self.vector[--self.x]
|
return self.vector[--self.x]
|
||||||
end
|
end
|
||||||
|
|
||||||
func __index(self, key)
|
function __index(self, key)
|
||||||
return self.vector[key]
|
return self.vector[key]
|
||||||
end
|
end
|
||||||
|
|
||||||
func __iter(self)
|
function __iter(self)
|
||||||
// you don't *have* to make a new object, i just wanted to show off anonymous functions
|
// you don't *have* to make a new object, i just wanted to show off anonymous functions
|
||||||
return {__next = (function(self)
|
return {__next = (function(self)
|
||||||
return self.vector[self.iterIndex++]
|
return self.vector[self.iterIndex++]
|
||||||
@ -27,9 +27,9 @@ proto Vector
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
let vector = Vector()
|
var vector = Vector()
|
||||||
|
|
||||||
for (let i = 0; i < 100000; i++) do
|
for (var i = 0; i < 100000; i++) do
|
||||||
vector:push(i)
|
vector:push(i)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
proto Range
|
proto Range
|
||||||
func __init(self, x)
|
function __init(self, x)
|
||||||
self.max = x
|
self.max = x
|
||||||
end
|
end
|
||||||
|
|
||||||
func __iter(self)
|
function __iter(self)
|
||||||
self.i = 0
|
self.i = 0
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
func __next(self)
|
function __next(self)
|
||||||
if self.i >= self.max then
|
if self.i >= self.max then
|
||||||
return nil // exit iterator loop
|
return nil // exit iterator loop
|
||||||
end
|
end
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
proto Test
|
proto Test
|
||||||
func __init(self, x)
|
function __init(self, x)
|
||||||
self.x = x
|
self.x = x
|
||||||
end
|
end
|
||||||
|
|
||||||
func print(self)
|
function print(self)
|
||||||
print(self.x)
|
print(self.x)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// stressing the GC
|
// stressing the GC
|
||||||
for (let i = 0; i < 100000; i++) do
|
for (var i = 0; i < 100000; i++) do
|
||||||
let x = Test("Hello world " .. i)
|
var x = Test("Hello world " .. i)
|
||||||
x:print()
|
x:print()
|
||||||
end
|
end
|
@ -1,7 +1,7 @@
|
|||||||
let words = "hello world! this is a sentence with words separated by space":split(" ")
|
var words = "hello world! this is a sentence with words separated by space":split(" ")
|
||||||
|
|
||||||
let str = ""
|
var str = ""
|
||||||
for (let i = 0; i < #words; i++) do
|
for (var i = 0; i < #words; i++) do
|
||||||
str = str .. words[i]
|
str = str .. words[i]
|
||||||
print(words[i])
|
print(words[i])
|
||||||
end
|
end
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// crafts a dummy proto
|
// crafts a dummy proto
|
||||||
proto test
|
proto test
|
||||||
func __init(self) end
|
function __init(self) end
|
||||||
end
|
end
|
||||||
|
|
||||||
// instance of test
|
// instance of test
|
||||||
let obj = test()
|
var obj = test()
|
||||||
|
|
||||||
test.__index = function(self, key)
|
test.__index = function(self, key)
|
||||||
print("__index called!")
|
print("__index called!")
|
||||||
|
@ -7,7 +7,7 @@ print("starting Testsuite...")
|
|||||||
// tests the string.* library
|
// tests the string.* library
|
||||||
|
|
||||||
assert("Hello world!":sub(6) == "world!", "string.sub() failed!")
|
assert("Hello world!":sub(6) == "world!", "string.sub() failed!")
|
||||||
assert("A":rep(6) == "AAAAAA", "string.rep() failed!")
|
assert("A":rep(6) == "AAAAAA", "string.red() failed!")
|
||||||
|
|
||||||
// tests some basic PEMDAS arithmetic
|
// tests some basic PEMDAS arithmetic
|
||||||
|
|
||||||
@ -17,16 +17,16 @@ assert(2 / 5 + 3 / 5 == 1, "PEMDAS check #2 failed!")
|
|||||||
// iterator test
|
// iterator test
|
||||||
|
|
||||||
proto Range
|
proto Range
|
||||||
func __init(self, x)
|
function __init(self, x)
|
||||||
self.max = x
|
self.max = x
|
||||||
end
|
end
|
||||||
|
|
||||||
func __iter(self)
|
function __iter(self)
|
||||||
self.i = 0
|
self.i = 0
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
func __next(self)
|
function __next(self)
|
||||||
if self.i >= self.max then
|
if self.i >= self.max then
|
||||||
return nil // exit iterator loop
|
return nil // exit iterator loop
|
||||||
end
|
end
|
||||||
@ -35,7 +35,7 @@ proto Range
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
let total = 0
|
var total = 0
|
||||||
for i in Range(100) do
|
for i in Range(100) do
|
||||||
total = total + i
|
total = total + i
|
||||||
end
|
end
|
||||||
|
@ -1,27 +1,27 @@
|
|||||||
proto test
|
proto test
|
||||||
func __init(self, x)
|
function __init(self, x)
|
||||||
self:setArg(x)
|
self:setArg(x)
|
||||||
end
|
end
|
||||||
|
|
||||||
func __tostring(self)
|
function __tostring(self)
|
||||||
let total = 1
|
var total = 1
|
||||||
|
|
||||||
for (let i = self.x; i > 0; i = i - 1) do
|
for (var i = self.x; i > 0; i = i - 1) do
|
||||||
total = total * i;
|
total = total * i;
|
||||||
end
|
end
|
||||||
|
|
||||||
return "The factorial of " .. self.x .. " is " .. total
|
return "The factorial of " .. self.x .. " is " .. total
|
||||||
end
|
end
|
||||||
|
|
||||||
func setArg(self, x)
|
function setArg(self, x)
|
||||||
self.x = x
|
self.x = x
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
let t = test(1)
|
var t = test(1)
|
||||||
|
|
||||||
for (let x = 1; x < 1000; x = x + 1) do
|
for (var x = 1; x < 1000; x = x + 1) do
|
||||||
for (let i = 1; i < 100; i = i + 1) do
|
for (var i = 1; i < 100; i = i + 1) do
|
||||||
t:setArg(i)
|
t:setArg(i)
|
||||||
|
|
||||||
print(t)
|
print(t)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// adds all args passed (expects numbers)
|
// adds all args passed (expects numbers)
|
||||||
func add(start, ...args)
|
function add(start, ...args)
|
||||||
// starting at `start`, add up all numbers passed
|
// starting at `start`, add up all numbers passed
|
||||||
local total = start
|
local total = start
|
||||||
for val in args do
|
for val in args do
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
// ================================================================ [BASELIB]
|
// ================================================================ [BASELIB]
|
||||||
|
// ================================================================
|
||||||
|
|
||||||
int cosmoB_print(CState *state, int nargs, CValue *args)
|
int cosmoB_print(CState *state, int nargs, CValue *args)
|
||||||
{
|
{
|
||||||
@ -163,6 +164,7 @@ void cosmoB_loadLibrary(CState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ================================================================ [OBJECT.*]
|
// ================================================================ [OBJECT.*]
|
||||||
|
// ================================================================
|
||||||
|
|
||||||
int cosmoB_osetProto(CState *state, int nargs, CValue *args)
|
int cosmoB_osetProto(CState *state, int nargs, CValue *args)
|
||||||
{
|
{
|
||||||
@ -253,6 +255,7 @@ COSMO_API void cosmoB_loadObjLib(CState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ================================================================ [OS.*]
|
// ================================================================ [OS.*]
|
||||||
|
// ================================================================
|
||||||
|
|
||||||
// os.read()
|
// os.read()
|
||||||
int cosmoB_osRead(CState *state, int nargs, CValue *args)
|
int cosmoB_osRead(CState *state, int nargs, CValue *args)
|
||||||
@ -350,6 +353,7 @@ COSMO_API void cosmoB_loadOSLib(CState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ================================================================ [STRING.*]
|
// ================================================================ [STRING.*]
|
||||||
|
// ================================================================
|
||||||
|
|
||||||
// string.sub
|
// string.sub
|
||||||
int cosmoB_sSub(CState *state, int nargs, CValue *args)
|
int cosmoB_sSub(CState *state, int nargs, CValue *args)
|
||||||
@ -625,6 +629,7 @@ void cosmoB_loadStrLib(CState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ================================================================ [MATH]
|
// ================================================================ [MATH]
|
||||||
|
// ================================================================
|
||||||
|
|
||||||
// math.abs
|
// math.abs
|
||||||
int cosmoB_mAbs(CState *state, int nargs, CValue *args)
|
int cosmoB_mAbs(CState *state, int nargs, CValue *args)
|
||||||
@ -842,6 +847,7 @@ void cosmoB_loadMathLib(CState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ================================================================ [VM.*]
|
// ================================================================ [VM.*]
|
||||||
|
// ================================================================
|
||||||
|
|
||||||
// vm.__getter["globals"]
|
// vm.__getter["globals"]
|
||||||
int cosmoB_vgetGlobal(CState *state, int nargs, CValue *args)
|
int cosmoB_vgetGlobal(CState *state, int nargs, CValue *args)
|
||||||
|
@ -56,6 +56,7 @@ int addConstant(CState *state, CChunk *chunk, CValue value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ================================================================ [WRITE TO CHUNK]
|
// ================================================================ [WRITE TO CHUNK]
|
||||||
|
// ================================================================
|
||||||
|
|
||||||
void writeu8Chunk(CState *state, CChunk *chunk, INSTRUCTION i, int line)
|
void writeu8Chunk(CState *state, CChunk *chunk, INSTRUCTION i, int line)
|
||||||
{
|
{
|
||||||
@ -70,8 +71,8 @@ void writeu8Chunk(CState *state, CChunk *chunk, INSTRUCTION i, int line)
|
|||||||
|
|
||||||
void writeu16Chunk(CState *state, CChunk *chunk, uint16_t i, int line)
|
void writeu16Chunk(CState *state, CChunk *chunk, uint16_t i, int line)
|
||||||
{
|
{
|
||||||
static const int sz = sizeof(uint16_t) / sizeof(INSTRUCTION);
|
|
||||||
INSTRUCTION *buffer = (INSTRUCTION *)(&i);
|
INSTRUCTION *buffer = (INSTRUCTION *)(&i);
|
||||||
|
int sz = sizeof(uint16_t) / sizeof(INSTRUCTION);
|
||||||
|
|
||||||
for (int i = 0; i < sz; i++) {
|
for (int i = 0; i < sz; i++) {
|
||||||
writeu8Chunk(state, chunk, buffer[i], line);
|
writeu8Chunk(state, chunk, buffer[i], line);
|
||||||
|
@ -14,7 +14,7 @@ CReservedWord reservedWords[] = {
|
|||||||
{ TOKEN_END, "end", 3},
|
{ TOKEN_END, "end", 3},
|
||||||
{ TOKEN_FALSE, "false", 5},
|
{ TOKEN_FALSE, "false", 5},
|
||||||
{ TOKEN_FOR, "for", 3},
|
{ TOKEN_FOR, "for", 3},
|
||||||
{ TOKEN_FUNC, "func", 4},
|
{TOKEN_FUNCTION, "function", 8},
|
||||||
{ TOKEN_IF, "if", 2},
|
{ TOKEN_IF, "if", 2},
|
||||||
{ TOKEN_IN, "in", 2},
|
{ TOKEN_IN, "in", 2},
|
||||||
{ TOKEN_LOCAL, "local", 5},
|
{ TOKEN_LOCAL, "local", 5},
|
||||||
@ -25,7 +25,7 @@ CReservedWord reservedWords[] = {
|
|||||||
{ TOKEN_RETURN, "return", 6},
|
{ TOKEN_RETURN, "return", 6},
|
||||||
{ TOKEN_THEN, "then", 4},
|
{ TOKEN_THEN, "then", 4},
|
||||||
{ TOKEN_TRUE, "true", 4},
|
{ TOKEN_TRUE, "true", 4},
|
||||||
{ TOKEN_LET, "let", 3},
|
{ TOKEN_VAR, "var", 3},
|
||||||
{ TOKEN_WHILE, "while", 5}
|
{ TOKEN_WHILE, "while", 5}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ typedef enum
|
|||||||
TOKEN_ELSEIF,
|
TOKEN_ELSEIF,
|
||||||
TOKEN_END,
|
TOKEN_END,
|
||||||
TOKEN_FOR,
|
TOKEN_FOR,
|
||||||
TOKEN_FUNC,
|
TOKEN_FUNCTION,
|
||||||
TOKEN_PROTO,
|
TOKEN_PROTO,
|
||||||
TOKEN_IF,
|
TOKEN_IF,
|
||||||
TOKEN_IN,
|
TOKEN_IN,
|
||||||
@ -66,7 +66,7 @@ typedef enum
|
|||||||
TOKEN_OR,
|
TOKEN_OR,
|
||||||
TOKEN_RETURN,
|
TOKEN_RETURN,
|
||||||
TOKEN_THEN,
|
TOKEN_THEN,
|
||||||
TOKEN_LET,
|
TOKEN_VAR,
|
||||||
TOKEN_WHILE,
|
TOKEN_WHILE,
|
||||||
|
|
||||||
TOKEN_ERROR,
|
TOKEN_ERROR,
|
||||||
|
14
src/cobj.c
14
src/cobj.c
@ -59,6 +59,12 @@ void cosmoO_free(CState *state, CObj *obj)
|
|||||||
cosmoM_free(state, CObjObject, objTbl);
|
cosmoM_free(state, CObjObject, objTbl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case COBJ_STREAM: {
|
||||||
|
CObjStream *objStrm = (CObjStream *)obj;
|
||||||
|
close(objStrm->fd);
|
||||||
|
cosmoM_free(state, CObjStream, objStrm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case COBJ_TABLE: {
|
case COBJ_TABLE: {
|
||||||
CObjTable *tbl = (CObjTable *)obj;
|
CObjTable *tbl = (CObjTable *)obj;
|
||||||
cosmoT_clearTable(state, &tbl->tbl);
|
cosmoT_clearTable(state, &tbl->tbl);
|
||||||
@ -198,6 +204,14 @@ CObjObject *cosmoO_newObject(CState *state)
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CObjStream *cosmoO_newStream(CState *state, int fd)
|
||||||
|
{
|
||||||
|
CObjStream *strm = (CObjStream *)cosmoO_allocateBase(state, sizeof(CObjStream), COBJ_STREAM);
|
||||||
|
strm->fd = fd;
|
||||||
|
|
||||||
|
return strm;
|
||||||
|
}
|
||||||
|
|
||||||
CObjTable *cosmoO_newTable(CState *state)
|
CObjTable *cosmoO_newTable(CState *state)
|
||||||
{
|
{
|
||||||
CObjTable *obj = (CObjTable *)cosmoO_allocateBase(state, sizeof(CObjTable), COBJ_TABLE);
|
CObjTable *obj = (CObjTable *)cosmoO_allocateBase(state, sizeof(CObjTable), COBJ_TABLE);
|
||||||
|
@ -48,6 +48,12 @@ struct CObjString
|
|||||||
bool isIString;
|
bool isIString;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CObjStream
|
||||||
|
{
|
||||||
|
CommonHeader; // "is a" CObj
|
||||||
|
int fd; // handle to file descriptor, on POSIX compliant OSes this can also be a socket :pog:
|
||||||
|
};
|
||||||
|
|
||||||
struct CObjError
|
struct CObjError
|
||||||
{
|
{
|
||||||
CommonHeader; // "is a" CObj
|
CommonHeader; // "is a" CObj
|
||||||
@ -132,6 +138,7 @@ struct CObjUpval
|
|||||||
|
|
||||||
#define cosmoV_readString(x) ((CObjString *)cosmoV_readRef(x))
|
#define cosmoV_readString(x) ((CObjString *)cosmoV_readRef(x))
|
||||||
#define cosmoV_readCString(x) (((CObjString *)cosmoV_readRef(x))->str)
|
#define cosmoV_readCString(x) (((CObjString *)cosmoV_readRef(x))->str)
|
||||||
|
#define cosmoV_readFD(x) (((CObjStream *)cosmoV_readRef(x))->fd)
|
||||||
#define cosmoV_readObject(x) ((CObjObject *)cosmoV_readRef(x))
|
#define cosmoV_readObject(x) ((CObjObject *)cosmoV_readRef(x))
|
||||||
#define cosmoV_readTable(x) ((CObjTable *)cosmoV_readRef(x))
|
#define cosmoV_readTable(x) ((CObjTable *)cosmoV_readRef(x))
|
||||||
#define cosmoV_readFunction(x) ((CObjFunction *)cosmoV_readRef(x))
|
#define cosmoV_readFunction(x) ((CObjFunction *)cosmoV_readRef(x))
|
||||||
@ -159,6 +166,7 @@ bool cosmoO_equal(CState *state, CObj *obj1, CObj *obj2);
|
|||||||
bool cosmoO_isDescendant(CObj *obj, CObjObject *proto);
|
bool cosmoO_isDescendant(CObj *obj, CObjObject *proto);
|
||||||
|
|
||||||
CObjObject *cosmoO_newObject(CState *state);
|
CObjObject *cosmoO_newObject(CState *state);
|
||||||
|
CObjStream *cosmoO_newStream(CState *state, int fd);
|
||||||
CObjTable *cosmoO_newTable(CState *state);
|
CObjTable *cosmoO_newTable(CState *state);
|
||||||
CObjFunction *cosmoO_newFunction(CState *state);
|
CObjFunction *cosmoO_newFunction(CState *state);
|
||||||
CObjCFunction *cosmoO_newCFunction(CState *state, CosmoCFunction func);
|
CObjCFunction *cosmoO_newCFunction(CState *state, CosmoCFunction func);
|
||||||
|
@ -34,6 +34,7 @@ typedef uint32_t cosmo_Flag;
|
|||||||
// objs
|
// objs
|
||||||
typedef struct CObj CObj;
|
typedef struct CObj CObj;
|
||||||
typedef struct CObjObject CObjObject;
|
typedef struct CObjObject CObjObject;
|
||||||
|
typedef struct CObjStream CObjStream;
|
||||||
typedef struct CObjString CObjString;
|
typedef struct CObjString CObjString;
|
||||||
typedef struct CObjUpval CObjUpval;
|
typedef struct CObjUpval CObjUpval;
|
||||||
typedef struct CObjFunction CObjFunction;
|
typedef struct CObjFunction CObjFunction;
|
||||||
|
77
src/cparse.c
77
src/cparse.c
@ -102,12 +102,13 @@ static int expressionPrecedence(CParseState *pstate, int needed, Precedence prec
|
|||||||
static int expression(CParseState *pstate, int needed, bool forceNeeded);
|
static int expression(CParseState *pstate, int needed, bool forceNeeded);
|
||||||
static void statement(CParseState *pstate);
|
static void statement(CParseState *pstate);
|
||||||
static void declaration(CParseState *pstate);
|
static void declaration(CParseState *pstate);
|
||||||
static void parseFunction(CParseState *pstate, FunctionType type);
|
static void function(CParseState *pstate, FunctionType type);
|
||||||
static void expressionStatement(CParseState *pstate);
|
static void expressionStatement(CParseState *pstate);
|
||||||
static ParseRule *getRule(CTokenType type);
|
static ParseRule *getRule(CTokenType type);
|
||||||
static CObjFunction *endCompiler(CParseState *pstate);
|
static CObjFunction *endCompiler(CParseState *pstate);
|
||||||
|
|
||||||
// ================================================================ [FRONT END/TALK TO LEXER]
|
// ================================================================ [FRONT END/TALK TO LEXER]
|
||||||
|
// ================================================================
|
||||||
|
|
||||||
static void initCompilerState(CParseState *pstate, CCompilerState *ccstate, FunctionType type,
|
static void initCompilerState(CParseState *pstate, CCompilerState *ccstate, FunctionType type,
|
||||||
CCompilerState *enclosing)
|
CCompilerState *enclosing)
|
||||||
@ -268,6 +269,7 @@ static bool blockFollow(CToken token)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ================================================================ [WRITE TO CHUNK]
|
// ================================================================ [WRITE TO CHUNK]
|
||||||
|
// ================================================================
|
||||||
|
|
||||||
CChunk *getChunk(CParseState *pstate)
|
CChunk *getChunk(CParseState *pstate)
|
||||||
{
|
{
|
||||||
@ -458,6 +460,7 @@ static bool isLast(CParseState *pstate, Precedence pType)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ================================================================ [PARSER]
|
// ================================================================ [PARSER]
|
||||||
|
// ================================================================
|
||||||
|
|
||||||
static void number(CParseState *pstate, bool canAssign, Precedence prec)
|
static void number(CParseState *pstate, bool canAssign, Precedence prec)
|
||||||
{
|
{
|
||||||
@ -590,40 +593,36 @@ static void group(CParseState *pstate, bool canAssign, Precedence prec)
|
|||||||
consume(pstate, TOKEN_RIGHT_PAREN, "Expected ')'");
|
consume(pstate, TOKEN_RIGHT_PAREN, "Expected ')'");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WRITE_GLOBAL_OP(pstate, op, arg)
|
static void _etterOP(CParseState *pstate, uint8_t op, int arg)
|
||||||
|
|
||||||
static void _etterAB(CParseState *pstate, uint8_t a, int b, bool isGlobal)
|
|
||||||
{
|
{
|
||||||
writeu8(pstate, a);
|
writeu8(pstate, op);
|
||||||
if (isGlobal) // globals are stored with a u16
|
if (op == OP_GETGLOBAL || op == OP_SETGLOBAL) // globals are stored with a u16
|
||||||
writeu16(pstate, b);
|
writeu16(pstate, arg);
|
||||||
else
|
else
|
||||||
writeu8(pstate, b);
|
writeu8(pstate, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void namedVariable(CParseState *pstate, CToken name, bool canAssign, bool canIncrement,
|
static void namedVariable(CParseState *pstate, CToken name, bool canAssign, bool canIncrement,
|
||||||
int expectedValues)
|
int expectedValues)
|
||||||
{
|
{
|
||||||
uint8_t opGet, opSet, opInc;
|
uint8_t opGet, opSet, inc;
|
||||||
bool isGlobal = false;
|
|
||||||
int arg = getLocal(pstate->compiler, &name);
|
int arg = getLocal(pstate->compiler, &name);
|
||||||
|
|
||||||
if (arg != -1) {
|
if (arg != -1) {
|
||||||
// we found it in our local table!
|
// we found it in out local table!
|
||||||
opGet = OP_GETLOCAL;
|
opGet = OP_GETLOCAL;
|
||||||
opSet = OP_SETLOCAL;
|
opSet = OP_SETLOCAL;
|
||||||
opInc = OP_INCLOCAL;
|
inc = OP_INCLOCAL;
|
||||||
} else if ((arg = getUpvalue(pstate, pstate->compiler, &name)) != -1) {
|
} else if ((arg = getUpvalue(pstate, pstate->compiler, &name)) != -1) {
|
||||||
opGet = OP_GETUPVAL;
|
opGet = OP_GETUPVAL;
|
||||||
opSet = OP_SETUPVAL;
|
opSet = OP_SETUPVAL;
|
||||||
opInc = OP_INCUPVAL;
|
inc = OP_INCUPVAL;
|
||||||
} else {
|
} else {
|
||||||
// local & upvalue wasn't found, assume it's a global!
|
// local & upvalue wasn't found, assume it's a global!
|
||||||
arg = identifierConstant(pstate, &name);
|
arg = identifierConstant(pstate, &name);
|
||||||
opGet = OP_GETGLOBAL;
|
opGet = OP_GETGLOBAL;
|
||||||
opSet = OP_SETGLOBAL;
|
opSet = OP_SETGLOBAL;
|
||||||
opInc = OP_INCGLOBAL;
|
inc = OP_INCGLOBAL;
|
||||||
isGlobal = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canAssign && match(pstate, TOKEN_COMMA)) {
|
if (canAssign && match(pstate, TOKEN_COMMA)) {
|
||||||
@ -632,7 +631,7 @@ static void namedVariable(CParseState *pstate, CToken name, bool canAssign, bool
|
|||||||
consume(pstate, TOKEN_IDENTIFIER, "Expected another identifer!");
|
consume(pstate, TOKEN_IDENTIFIER, "Expected another identifer!");
|
||||||
|
|
||||||
namedVariable(pstate, pstate->previous, true, false, expectedValues);
|
namedVariable(pstate, pstate->previous, true, false, expectedValues);
|
||||||
_etterAB(pstate, opSet, arg, isGlobal);
|
_etterOP(pstate, opSet, arg);
|
||||||
valuePopped(pstate, 1);
|
valuePopped(pstate, 1);
|
||||||
} else if (canAssign && match(pstate, TOKEN_EQUAL)) {
|
} else if (canAssign && match(pstate, TOKEN_EQUAL)) {
|
||||||
expectedValues++;
|
expectedValues++;
|
||||||
@ -655,21 +654,29 @@ static void namedVariable(CParseState *pstate, CToken name, bool canAssign, bool
|
|||||||
writeu8(pstate, OP_NIL);
|
writeu8(pstate, OP_NIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
_etterAB(pstate, opSet, arg, isGlobal);
|
_etterOP(pstate, opSet, arg);
|
||||||
valuePopped(pstate, 1);
|
valuePopped(pstate, 1);
|
||||||
} else if (canIncrement && match(pstate, TOKEN_PLUS_PLUS)) { // i++
|
} else if (canIncrement && match(pstate, TOKEN_PLUS_PLUS)) { // i++
|
||||||
// now we increment the value
|
// now we increment the value
|
||||||
writeu8(pstate, opInc);
|
writeu8(pstate, inc);
|
||||||
_etterAB(pstate, 128 + 1, arg, isGlobal); // As B(x?)
|
writeu8(pstate, 128 + 1); // setting signed values in an unsigned int
|
||||||
|
if (inc == OP_INCGLOBAL) // globals are stored with a u16
|
||||||
|
writeu16(pstate, arg);
|
||||||
|
else
|
||||||
|
writeu8(pstate, arg);
|
||||||
valuePushed(pstate, 1);
|
valuePushed(pstate, 1);
|
||||||
} else if (canIncrement && match(pstate, TOKEN_MINUS_MINUS)) { // i--
|
} else if (canIncrement && match(pstate, TOKEN_MINUS_MINUS)) { // i--
|
||||||
// now we increment the value
|
// now we increment the value
|
||||||
writeu8(pstate, opInc);
|
writeu8(pstate, inc);
|
||||||
_etterAB(pstate, 128 - 1, arg, isGlobal); // As B(x?)
|
writeu8(pstate, 128 - 1); // setting signed values in an unsigned int
|
||||||
|
if (inc == OP_INCGLOBAL) // globals are stored with a u16
|
||||||
|
writeu16(pstate, arg);
|
||||||
|
else
|
||||||
|
writeu8(pstate, arg);
|
||||||
valuePushed(pstate, 1);
|
valuePushed(pstate, 1);
|
||||||
} else {
|
} else {
|
||||||
// getter
|
// getter
|
||||||
_etterAB(pstate, opGet, arg, isGlobal);
|
_etterOP(pstate, opGet, arg);
|
||||||
valuePushed(pstate, 1);
|
valuePushed(pstate, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -701,7 +708,7 @@ static void or_(CParseState *pstate, bool canAssign, Precedence prec)
|
|||||||
|
|
||||||
static void anonFunction(CParseState *pstate, bool canAssign, Precedence prec)
|
static void anonFunction(CParseState *pstate, bool canAssign, Precedence prec)
|
||||||
{
|
{
|
||||||
parseFunction(pstate, FTYPE_FUNCTION);
|
function(pstate, FTYPE_FUNCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void variable(CParseState *pstate, bool canAssign, Precedence prec)
|
static void variable(CParseState *pstate, bool canAssign, Precedence prec)
|
||||||
@ -1075,7 +1082,7 @@ ParseRule ruleTable[] = {
|
|||||||
[TOKEN_ELSEIF] = {NULL, NULL, PREC_NONE},
|
[TOKEN_ELSEIF] = {NULL, NULL, PREC_NONE},
|
||||||
[TOKEN_END] = {NULL, NULL, PREC_NONE},
|
[TOKEN_END] = {NULL, NULL, PREC_NONE},
|
||||||
[TOKEN_FOR] = {NULL, NULL, PREC_NONE},
|
[TOKEN_FOR] = {NULL, NULL, PREC_NONE},
|
||||||
[TOKEN_FUNC] = {anonFunction, NULL, PREC_NONE},
|
[TOKEN_FUNCTION] = {anonFunction, NULL, PREC_NONE},
|
||||||
[TOKEN_PROTO] = {NULL, NULL, PREC_NONE},
|
[TOKEN_PROTO] = {NULL, NULL, PREC_NONE},
|
||||||
[TOKEN_IF] = {NULL, NULL, PREC_NONE},
|
[TOKEN_IF] = {NULL, NULL, PREC_NONE},
|
||||||
[TOKEN_IN] = {NULL, NULL, PREC_NONE},
|
[TOKEN_IN] = {NULL, NULL, PREC_NONE},
|
||||||
@ -1086,7 +1093,7 @@ ParseRule ruleTable[] = {
|
|||||||
[TOKEN_THEN] = {NULL, NULL, PREC_NONE},
|
[TOKEN_THEN] = {NULL, NULL, PREC_NONE},
|
||||||
[TOKEN_WHILE] = {NULL, NULL, PREC_NONE},
|
[TOKEN_WHILE] = {NULL, NULL, PREC_NONE},
|
||||||
[TOKEN_ERROR] = {NULL, NULL, PREC_NONE},
|
[TOKEN_ERROR] = {NULL, NULL, PREC_NONE},
|
||||||
[TOKEN_LET] = {NULL, NULL, PREC_NONE},
|
[TOKEN_VAR] = {NULL, NULL, PREC_NONE},
|
||||||
[TOKEN_EOF] = {NULL, NULL, PREC_NONE}
|
[TOKEN_EOF] = {NULL, NULL, PREC_NONE}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1178,7 +1185,7 @@ static void _proto(CParseState *pstate)
|
|||||||
int entries = 0;
|
int entries = 0;
|
||||||
|
|
||||||
while (!match(pstate, TOKEN_END) && !match(pstate, TOKEN_EOF) && !pstate->hadError) {
|
while (!match(pstate, TOKEN_END) && !match(pstate, TOKEN_EOF) && !pstate->hadError) {
|
||||||
if (match(pstate, TOKEN_FUNC)) {
|
if (match(pstate, TOKEN_FUNCTION)) {
|
||||||
// define method
|
// define method
|
||||||
consume(pstate, TOKEN_IDENTIFIER, "Expected identifier for method!");
|
consume(pstate, TOKEN_IDENTIFIER, "Expected identifier for method!");
|
||||||
uint16_t fieldIdent = identifierConstant(pstate, &pstate->previous);
|
uint16_t fieldIdent = identifierConstant(pstate, &pstate->previous);
|
||||||
@ -1187,7 +1194,7 @@ static void _proto(CParseState *pstate)
|
|||||||
writeu8(pstate, OP_LOADCONST);
|
writeu8(pstate, OP_LOADCONST);
|
||||||
writeu16(pstate, fieldIdent);
|
writeu16(pstate, fieldIdent);
|
||||||
|
|
||||||
parseFunction(pstate, FTYPE_METHOD);
|
function(pstate, FTYPE_METHOD);
|
||||||
valuePopped(pstate, 1);
|
valuePopped(pstate, 1);
|
||||||
} else {
|
} else {
|
||||||
errorAtCurrent(pstate, "Illegal syntax!");
|
errorAtCurrent(pstate, "Illegal syntax!");
|
||||||
@ -1405,7 +1412,7 @@ static void whileStatement(CParseState *pstate)
|
|||||||
patchJmp(pstate, exitJump);
|
patchJmp(pstate, exitJump);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parseFunction(CParseState *pstate, FunctionType type)
|
static void function(CParseState *pstate, FunctionType type)
|
||||||
{
|
{
|
||||||
CCompilerState compiler;
|
CCompilerState compiler;
|
||||||
initCompilerState(pstate, &compiler, type, pstate->compiler);
|
initCompilerState(pstate, &compiler, type, pstate->compiler);
|
||||||
@ -1471,7 +1478,7 @@ static void functionDeclaration(CParseState *pstate)
|
|||||||
if (pstate->compiler->scopeDepth > 0)
|
if (pstate->compiler->scopeDepth > 0)
|
||||||
markInitialized(pstate, var);
|
markInitialized(pstate, var);
|
||||||
|
|
||||||
parseFunction(pstate, FTYPE_FUNCTION);
|
function(pstate, FTYPE_FUNCTION);
|
||||||
|
|
||||||
defineVariable(pstate, var, false);
|
defineVariable(pstate, var, false);
|
||||||
}
|
}
|
||||||
@ -1502,12 +1509,12 @@ static void returnStatement(CParseState *pstate)
|
|||||||
valuePopped(pstate, rvalues);
|
valuePopped(pstate, rvalues);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void localparseFunction(CParseState *pstate)
|
static void localFunction(CParseState *pstate)
|
||||||
{
|
{
|
||||||
uint16_t var = parseVariable(pstate, "Expected identifer!", true);
|
uint16_t var = parseVariable(pstate, "Expected identifer!", true);
|
||||||
markInitialized(pstate, var);
|
markInitialized(pstate, var);
|
||||||
|
|
||||||
parseFunction(pstate, FTYPE_FUNCTION);
|
function(pstate, FTYPE_FUNCTION);
|
||||||
|
|
||||||
defineVariable(pstate, var, true);
|
defineVariable(pstate, var, true);
|
||||||
}
|
}
|
||||||
@ -1728,12 +1735,12 @@ static void expressionStatement(CParseState *pstate)
|
|||||||
{
|
{
|
||||||
int savedPushed = pstate->compiler->pushedValues;
|
int savedPushed = pstate->compiler->pushedValues;
|
||||||
|
|
||||||
if (match(pstate, TOKEN_LET)) {
|
if (match(pstate, TOKEN_VAR)) {
|
||||||
varDeclaration(pstate, false, 0);
|
varDeclaration(pstate, false, 0);
|
||||||
} else if (match(pstate, TOKEN_LOCAL)) {
|
} else if (match(pstate, TOKEN_LOCAL)) {
|
||||||
// force declare a local
|
// force declare a local
|
||||||
if (match(pstate, TOKEN_FUNC))
|
if (match(pstate, TOKEN_FUNCTION))
|
||||||
localparseFunction(pstate); // force a local function declaration
|
localFunction(pstate); // force a local function declaration
|
||||||
else if (match(pstate, TOKEN_PROTO))
|
else if (match(pstate, TOKEN_PROTO))
|
||||||
localProto(pstate); // force a local proto declaration
|
localProto(pstate); // force a local proto declaration
|
||||||
else
|
else
|
||||||
@ -1748,7 +1755,7 @@ static void expressionStatement(CParseState *pstate)
|
|||||||
whileStatement(pstate);
|
whileStatement(pstate);
|
||||||
} else if (match(pstate, TOKEN_FOR)) {
|
} else if (match(pstate, TOKEN_FOR)) {
|
||||||
forLoop(pstate);
|
forLoop(pstate);
|
||||||
} else if (match(pstate, TOKEN_FUNC)) {
|
} else if (match(pstate, TOKEN_FUNCTION)) {
|
||||||
functionDeclaration(pstate);
|
functionDeclaration(pstate);
|
||||||
} else if (match(pstate, TOKEN_PROTO)) {
|
} else if (match(pstate, TOKEN_PROTO)) {
|
||||||
protoDeclaration(pstate);
|
protoDeclaration(pstate);
|
||||||
|
@ -59,7 +59,8 @@ struct CState
|
|||||||
|
|
||||||
CValue *top; // top of the stack
|
CValue *top; // top of the stack
|
||||||
CObjObject *protoObjects[COBJ_MAX]; // proto object for each COBJ type [NULL = no default proto]
|
CObjObject *protoObjects[COBJ_MAX]; // proto object for each COBJ type [NULL = no default proto]
|
||||||
CObjString *iStrings[ISTRING_MAX]; // strings used internally by the VM, eg. __init, __index
|
CObjString
|
||||||
|
*iStrings[ISTRING_MAX]; // strings used internally by the VM, eg. __init, __index & friends
|
||||||
CCallFrame callFrame[FRAME_MAX]; // call frames
|
CCallFrame callFrame[FRAME_MAX]; // call frames
|
||||||
CValue stack[STACK_MAX]; // stack
|
CValue stack[STACK_MAX]; // stack
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user