syntax: 'var'->'let' 'function'->'func'

- 'var' has some weird scoping connotations with users of JS. better to change it to 'let', which will decide whether to make the variable a local or a global
- 'func' looks visually appealing lol
- some minor refactoring done in cparse.c
This commit is contained in:
CPunch 2023-02-09 15:58:25 -06:00 committed by cpunch
parent e335fd95d6
commit 8ac8085d20
16 changed files with 95 additions and 99 deletions

View File

@ -5,31 +5,31 @@ Cosmo is a portable scripting language loosely based off of Lua. Cosmo easily al
```lua ```lua
proto Vector proto Vector
function __init(self) func __init(self)
self.vector = [] self.vector = []
self.x = 0 self.x = 0
end end
function __index(self, key) func __index(self, key)
return self.vector[key] return self.vector[key]
end end
function push(self, val) func push(self, val)
self.vector[self.x++] = val self.vector[self.x++] = val
end end
function pop(self) func pop(self)
return self.vector[--self.x] return self.vector[--self.x]
end end
end end
var vector = Vector() let vector = Vector()
for (var i = 0; i < 4; i++) do for (let i = 0; i < 4; i++) do
vector:push(i) vector:push(i)
end end
for (var i = 0; i < 4; i++) do for (let i = 0; i < 4; i++) do
print(vector:pop() .. " : " .. vector[i]) print(vector:pop() .. " : " .. vector[i])
end end
``` ```

View File

@ -1,8 +1,8 @@
// just testing continues and breaks // just testing continues and breaks
for (var x = 0; x < 700; x++) do for (let x = 0; x < 700; x++) do
for (var i = 0; true; i++) do for (let i = 0; true; i++) do
var str = i .. "." .. x let 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 (var 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
var i = 0 let i = 0
while true do while true do
var str = i .. "." .. x let str = i .. "." .. x
if (i++ == 998) then if (i++ == 998) then
print("done") print("done")
break break

View File

@ -1,20 +1,20 @@
var strtable = [] let strtable = []
var strLen = 4 // length of all strings to generate let strLen = 4 // length of all strings to generate
var AByte = "A":byte() // grabs the ascii value of 'A' let AByte = "A":byte() // grabs the ascii value of 'A'
proto stringBuilder proto stringBuilder
function __init(self, length) func __init(self, length)
self.len = length self.len = length
end end
// we are the iterator object lol // we are the iterator object lol
function __iter(self) func __iter(self)
self.x = 0 self.x = 0
return self return self
end end
function __next(self) func __next(self)
var x = self.x++ let 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
var str = "" let str = ""
for (var i = 0; i < self.len; i++) do for (let 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)

View File

@ -1,4 +1,4 @@
local function fib(num) local func fib(num)
if num <= 1 then if num <= 1 then
return num return num
else else
@ -6,6 +6,6 @@ local function fib(num)
end end
end end
for (var i = 1; i < 40; i++) do for (let 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

View File

@ -1,4 +1,4 @@
var object = { let object = {
__setter = [ __setter = [
"field1" = function(self, val) "field1" = function(self, val)
print("setter for field1 called!") print("setter for field1 called!")

View File

@ -1,22 +1,22 @@
proto Vector proto Vector
function __init(self) func __init(self)
self.vector = [] self.vector = []
self.x = 0 self.x = 0
end end
function push(self, val) func push(self, val)
self.vector[self.x++] = val self.vector[self.x++] = val
end end
function pop(self) func pop(self)
return self.vector[--self.x] return self.vector[--self.x]
end end
function __index(self, key) func __index(self, key)
return self.vector[key] return self.vector[key]
end end
function __iter(self) func __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
var vector = Vector() let vector = Vector()
for (var i = 0; i < 100000; i++) do for (let i = 0; i < 100000; i++) do
vector:push(i) vector:push(i)
end end

View File

@ -1,14 +1,14 @@
proto Range proto Range
function __init(self, x) func __init(self, x)
self.max = x self.max = x
end end
function __iter(self) func __iter(self)
self.i = 0 self.i = 0
return self return self
end end
function __next(self) func __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

View File

@ -1,15 +1,15 @@
proto Test proto Test
function __init(self, x) func __init(self, x)
self.x = x self.x = x
end end
function print(self) func print(self)
print(self.x) print(self.x)
end end
end end
// stressing the GC // stressing the GC
for (var i = 0; i < 100000; i++) do for (let i = 0; i < 100000; i++) do
var x = Test("Hello world " .. i) let x = Test("Hello world " .. i)
x:print() x:print()
end end

View File

@ -1,7 +1,7 @@
var words = "hello world! this is a sentence with words separated by space":split(" ") let words = "hello world! this is a sentence with words separated by space":split(" ")
var str = "" let str = ""
for (var i = 0; i < #words; i++) do for (let i = 0; i < #words; i++) do
str = str .. words[i] str = str .. words[i]
print(words[i]) print(words[i])
end end

View File

@ -1,10 +1,10 @@
// crafts a dummy proto // crafts a dummy proto
proto test proto test
function __init(self) end func __init(self) end
end end
// instance of test // instance of test
var obj = test() let obj = test()
test.__index = function(self, key) test.__index = function(self, key)
print("__index called!") print("__index called!")

View File

@ -17,16 +17,16 @@ assert(2 / 5 + 3 / 5 == 1, "PEMDAS check #2 failed!")
// iterator test // iterator test
proto Range proto Range
function __init(self, x) func __init(self, x)
self.max = x self.max = x
end end
function __iter(self) func __iter(self)
self.i = 0 self.i = 0
return self return self
end end
function __next(self) func __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
var total = 0 let total = 0
for i in Range(100) do for i in Range(100) do
total = total + i total = total + i
end end

View File

@ -1,27 +1,27 @@
proto test proto test
function __init(self, x) func __init(self, x)
self:setArg(x) self:setArg(x)
end end
function __tostring(self) func __tostring(self)
var total = 1 let total = 1
for (var i = self.x; i > 0; i = i - 1) do for (let 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
function setArg(self, x) func setArg(self, x)
self.x = x self.x = x
end end
end end
var t = test(1) let t = test(1)
for (var x = 1; x < 1000; x = x + 1) do for (let x = 1; x < 1000; x = x + 1) do
for (var i = 1; i < 100; i = i + 1) do for (let i = 1; i < 100; i = i + 1) do
t:setArg(i) t:setArg(i)
print(t) print(t)

View File

@ -1,5 +1,5 @@
// adds all args passed (expects numbers) // adds all args passed (expects numbers)
function add(start, ...args) func 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

View File

@ -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_FUNCTION, "function", 8}, { TOKEN_FUNC, "func", 4},
{ 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_VAR, "var", 3}, { TOKEN_LET, "let", 3},
{ TOKEN_WHILE, "while", 5} { TOKEN_WHILE, "while", 5}
}; };

View File

@ -57,7 +57,7 @@ typedef enum
TOKEN_ELSEIF, TOKEN_ELSEIF,
TOKEN_END, TOKEN_END,
TOKEN_FOR, TOKEN_FOR,
TOKEN_FUNCTION, TOKEN_FUNC,
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_VAR, TOKEN_LET,
TOKEN_WHILE, TOKEN_WHILE,
TOKEN_ERROR, TOKEN_ERROR,

View File

@ -102,7 +102,7 @@ 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 function(CParseState *pstate, FunctionType type); static void parseFunction(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);
@ -590,36 +590,40 @@ static void group(CParseState *pstate, bool canAssign, Precedence prec)
consume(pstate, TOKEN_RIGHT_PAREN, "Expected ')'"); consume(pstate, TOKEN_RIGHT_PAREN, "Expected ')'");
} }
static void _etterOP(CParseState *pstate, uint8_t op, int arg) #define WRITE_GLOBAL_OP(pstate, op, arg)
static void _etterAB(CParseState *pstate, uint8_t a, int b, bool isGlobal)
{ {
writeu8(pstate, op); writeu8(pstate, a);
if (op == OP_GETGLOBAL || op == OP_SETGLOBAL) // globals are stored with a u16 if (isGlobal) // globals are stored with a u16
writeu16(pstate, arg); writeu16(pstate, b);
else else
writeu8(pstate, arg); writeu8(pstate, b);
} }
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, inc; uint8_t opGet, opSet, opInc;
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 out local table! // we found it in our local table!
opGet = OP_GETLOCAL; opGet = OP_GETLOCAL;
opSet = OP_SETLOCAL; opSet = OP_SETLOCAL;
inc = OP_INCLOCAL; opInc = 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;
inc = OP_INCUPVAL; opInc = 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;
inc = OP_INCGLOBAL; opInc = OP_INCGLOBAL;
isGlobal = true;
} }
if (canAssign && match(pstate, TOKEN_COMMA)) { if (canAssign && match(pstate, TOKEN_COMMA)) {
@ -628,7 +632,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);
_etterOP(pstate, opSet, arg); _etterAB(pstate, opSet, arg, isGlobal);
valuePopped(pstate, 1); valuePopped(pstate, 1);
} else if (canAssign && match(pstate, TOKEN_EQUAL)) { } else if (canAssign && match(pstate, TOKEN_EQUAL)) {
expectedValues++; expectedValues++;
@ -651,29 +655,21 @@ static void namedVariable(CParseState *pstate, CToken name, bool canAssign, bool
writeu8(pstate, OP_NIL); writeu8(pstate, OP_NIL);
} }
_etterOP(pstate, opSet, arg); _etterAB(pstate, opSet, arg, isGlobal);
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, inc); writeu8(pstate, opInc);
writeu8(pstate, 128 + 1); // setting signed values in an unsigned int _etterAB(pstate, 128 + 1, arg, isGlobal); // As B(x?)
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, inc); writeu8(pstate, opInc);
writeu8(pstate, 128 - 1); // setting signed values in an unsigned int _etterAB(pstate, 128 - 1, arg, isGlobal); // As B(x?)
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
_etterOP(pstate, opGet, arg); _etterAB(pstate, opGet, arg, isGlobal);
valuePushed(pstate, 1); valuePushed(pstate, 1);
} }
} }
@ -705,7 +701,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)
{ {
function(pstate, FTYPE_FUNCTION); parseFunction(pstate, FTYPE_FUNCTION);
} }
static void variable(CParseState *pstate, bool canAssign, Precedence prec) static void variable(CParseState *pstate, bool canAssign, Precedence prec)
@ -1079,7 +1075,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_FUNCTION] = {anonFunction, NULL, PREC_NONE}, [TOKEN_FUNC] = {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},
@ -1090,7 +1086,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_VAR] = {NULL, NULL, PREC_NONE}, [TOKEN_LET] = {NULL, NULL, PREC_NONE},
[TOKEN_EOF] = {NULL, NULL, PREC_NONE} [TOKEN_EOF] = {NULL, NULL, PREC_NONE}
}; };
@ -1182,7 +1178,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_FUNCTION)) { if (match(pstate, TOKEN_FUNC)) {
// 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);
@ -1191,7 +1187,7 @@ static void _proto(CParseState *pstate)
writeu8(pstate, OP_LOADCONST); writeu8(pstate, OP_LOADCONST);
writeu16(pstate, fieldIdent); writeu16(pstate, fieldIdent);
function(pstate, FTYPE_METHOD); parseFunction(pstate, FTYPE_METHOD);
valuePopped(pstate, 1); valuePopped(pstate, 1);
} else { } else {
errorAtCurrent(pstate, "Illegal syntax!"); errorAtCurrent(pstate, "Illegal syntax!");
@ -1409,7 +1405,7 @@ static void whileStatement(CParseState *pstate)
patchJmp(pstate, exitJump); patchJmp(pstate, exitJump);
} }
static void function(CParseState *pstate, FunctionType type) static void parseFunction(CParseState *pstate, FunctionType type)
{ {
CCompilerState compiler; CCompilerState compiler;
initCompilerState(pstate, &compiler, type, pstate->compiler); initCompilerState(pstate, &compiler, type, pstate->compiler);
@ -1475,7 +1471,7 @@ static void functionDeclaration(CParseState *pstate)
if (pstate->compiler->scopeDepth > 0) if (pstate->compiler->scopeDepth > 0)
markInitialized(pstate, var); markInitialized(pstate, var);
function(pstate, FTYPE_FUNCTION); parseFunction(pstate, FTYPE_FUNCTION);
defineVariable(pstate, var, false); defineVariable(pstate, var, false);
} }
@ -1506,12 +1502,12 @@ static void returnStatement(CParseState *pstate)
valuePopped(pstate, rvalues); valuePopped(pstate, rvalues);
} }
static void localFunction(CParseState *pstate) static void localparseFunction(CParseState *pstate)
{ {
uint16_t var = parseVariable(pstate, "Expected identifer!", true); uint16_t var = parseVariable(pstate, "Expected identifer!", true);
markInitialized(pstate, var); markInitialized(pstate, var);
function(pstate, FTYPE_FUNCTION); parseFunction(pstate, FTYPE_FUNCTION);
defineVariable(pstate, var, true); defineVariable(pstate, var, true);
} }
@ -1732,12 +1728,12 @@ static void expressionStatement(CParseState *pstate)
{ {
int savedPushed = pstate->compiler->pushedValues; int savedPushed = pstate->compiler->pushedValues;
if (match(pstate, TOKEN_VAR)) { if (match(pstate, TOKEN_LET)) {
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_FUNCTION)) if (match(pstate, TOKEN_FUNC))
localFunction(pstate); // force a local function declaration localparseFunction(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
@ -1752,7 +1748,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_FUNCTION)) { } else if (match(pstate, TOKEN_FUNC)) {
functionDeclaration(pstate); functionDeclaration(pstate);
} else if (match(pstate, TOKEN_PROTO)) { } else if (match(pstate, TOKEN_PROTO)) {
protoDeclaration(pstate); protoDeclaration(pstate);