Skip to content

Commit

Permalink
Merge pull request #238 from PlutoLang/use
Browse files Browse the repository at this point in the history
Add pluto_use
  • Loading branch information
Sainan authored Apr 12, 2023
2 parents 3980f5f + 075d141 commit 1d395bb
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 87 deletions.
26 changes: 2 additions & 24 deletions src/llex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,31 +46,9 @@ static const char *const luaX_tokens [] = {
"end", "false", "for", "function", "goto", "if",
"in", "local", "nil", "not", "or", "repeat",
"case", "default", "as", "begin", "extends", "instanceof",
#ifdef PLUTO_COMPATIBLE_CLASS
"class",
#endif
"pluto_use",
"pluto_switch", "pluto_continue", "pluto_enum", "pluto_new", "pluto_class", "pluto_parent", "pluto_export",
#ifndef PLUTO_COMPATIBLE_SWITCH
"switch",
#endif
#ifndef PLUTO_COMPATIBLE_CONTINUE
"continue",
#endif
#ifndef PLUTO_COMPATIBLE_ENUM
"enum",
#endif
#ifndef PLUTO_COMPATIBLE_NEW
"new",
#endif
#ifndef PLUTO_COMPATIBLE_CLASS
"class",
#endif
#ifndef PLUTO_COMPATIBLE_PARENT
"parent",
#endif
#ifndef PLUTO_COMPATIBLE_EXPORT
"export",
#endif
"switch", "continue", "enum", "new", "class", "parent", "export",
"pluto_suggest_0", "pluto_suggest_1",
"return", "then", "true", "until", "while",
"//", "..", "...", "==", ">=", "<=", "~=",
Expand Down
52 changes: 22 additions & 30 deletions src/llex.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,32 +39,9 @@ enum RESERVED {
TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
TK_CASE, TK_DEFAULT, TK_AS, TK_BEGIN, TK_EXTENDS, TK_INSTANCEOF, // New narrow keywords.
#ifdef PLUTO_COMPATIBLE_CLASS
TK_CLASS,
#endif
TK_PSWITCH, TK_PCONTINUE, TK_PENUM, TK_PNEW, TK_PCLASS, TK_PPARENT, TK_PEXPORT, // New compatibility keywords.
/* New non-compatible keywords. */
#ifndef PLUTO_COMPATIBLE_SWITCH
TK_SWITCH,
#endif
#ifndef PLUTO_COMPATIBLE_CONTINUE
TK_CONTINUE,
#endif
#ifndef PLUTO_COMPATIBLE_ENUM
TK_ENUM,
#endif
#ifndef PLUTO_COMPATIBLE_NEW
TK_NEW,
#endif
#ifndef PLUTO_COMPATIBLE_CLASS
TK_CLASS,
#endif
#ifndef PLUTO_COMPATIBLE_PARENT
TK_PARENT,
#endif
#ifndef PLUTO_COMPATIBLE_EXPORT
TK_EXPORT,
#endif
TK_PUSE, // New compatibility keywords.
TK_PSWITCH, TK_PCONTINUE, TK_PENUM, TK_PNEW, TK_PCLASS, TK_PPARENT, TK_PEXPORT,
TK_SWITCH, TK_CONTINUE, TK_ENUM, TK_NEW, TK_CLASS, TK_PARENT, TK_EXPORT, // New non-compatible keywords.
TK_SUGGEST_0, TK_SUGGEST_1, // New special keywords.
TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
/* other terminal symbols */
Expand All @@ -87,6 +64,9 @@ enum RESERVED {
TK_WALRUS, /* walrus operator */
};

#define FIRST_COMPAT TK_PUSE
#define FIRST_NON_COMPAT TK_PSWITCH
#define FIRST_SPECIAL TK_SUGGEST_0
#define LAST_RESERVED TK_WHILE

/* number of reserved words */
Expand Down Expand Up @@ -159,12 +139,24 @@ struct Token {
[[nodiscard]] bool IsNarrow() const noexcept
{
return token == TK_IN
|| (token >= TK_CASE && token < TK_PSWITCH)
#ifdef PLUTO_COMPATIBLE_CLASS
|| token == TK_CLASS
#endif
|| (token >= TK_CASE && token < FIRST_COMPAT)
;
}

[[nodiscard]] bool IsCompatible() const noexcept
{
return (token >= FIRST_COMPAT && token < FIRST_NON_COMPAT);
}

[[nodiscard]] bool IsNonCompatible() const noexcept
{
return (token >= FIRST_NON_COMPAT && token < FIRST_SPECIAL);
}

[[nodiscard]] bool IsSpecial() const noexcept
{
return (token >= FIRST_SPECIAL && token < TK_RETURN);
}
};


Expand Down
133 changes: 100 additions & 33 deletions src/lparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1500,11 +1500,7 @@ static void classexpr (LexState *ls, expdesc *t) {
field(ls, &cc);
(testnext(ls, ',') || testnext(ls, ';'));
}
#ifdef PLUTO_COMPATIBLE_CLASS
check_match(ls, TK_END, TK_PCLASS, line);
#else
check_match(ls, TK_END, TK_CLASS, line);
#endif
lastlistfield(fs, &cc);
luaK_settablesize(fs, pc, t->u.info, cc.na, cc.nh);
}
Expand Down Expand Up @@ -2390,9 +2386,7 @@ static void primaryexp (LexState *ls, expdesc *v) {
}
return;
}
#ifndef PLUTO_COMPATIBLE_PARENT
case TK_PARENT:
#endif
case TK_PPARENT: {
luaX_next(ls);
parentexp(ls, v);
Expand Down Expand Up @@ -2599,17 +2593,13 @@ static void simpleexp (LexState *ls, expdesc *v, int flags, TypeDesc *prop) {
lambdabody(ls, v, ls->getLineNumber());
return;
}
#ifndef PLUTO_COMPATIBLE_NEW
case TK_NEW:
#endif
case TK_PNEW: {
if (prop) *prop = VT_TABLE;
newexpr(ls, v);
return;
}
#ifndef PLUTO_COMPATIBLE_CLASS
case TK_CLASS:
#endif
case TK_PCLASS: {
if (prop) *prop = VT_TABLE;
luaX_next(ls); /* skip 'class' */
Expand Down Expand Up @@ -3258,7 +3248,9 @@ static void enumstat (LexState *ls) {
EnumDesc *ed = nullptr;
bool is_enum_class = false;
if (gett(ls) != TK_BEGIN) { /* enum has name (and possibly modifier)? */
if (gett(ls) == TK_CLASS) {
if (ls->t.token == TK_CLASS
|| (ls->t.token == TK_NAME && strcmp(ls->t.seminfo.ts->contents, "class") == 0)
) {
is_enum_class = true;
luaX_next(ls);
}
Expand Down Expand Up @@ -3918,6 +3910,76 @@ static void retstat (LexState *ls, TypeDesc *prop) {
}


static int checkkeyword (LexState *ls) {
if (ls->t.token == TK_NAME)
for (int i = FIRST_NON_COMPAT; i != FIRST_SPECIAL; ++i)
if (strcmp(luaX_reserved2str(i), ls->t.seminfo.ts->contents) == 0) {
luaX_next(ls);
return i;
}
if (!ls->t.IsNonCompatible()) {
if (ls->t.IsCompatible())
luaX_syntaxerror(ls, "expected non-compatible keyword");
luaX_syntaxerror(ls, "expected keyword");
}
int token = ls->t.token;
luaX_next(ls);
return token;
}

static void disablekeyword (LexState *ls, int token) {
auto i = ls->tokens.begin();
if (ls->tidx != -1)
i += ls->tidx; /* don't apply retroactively */
for (; i != ls->tokens.end(); ++i)
if (i->token == token)
i->token = TK_NAME;
}


static void enablekeyword (LexState *ls, int token) {
const char* str = luaX_reserved2str(token);
auto i = ls->tokens.begin() + ls->tidx;
TString* ts = nullptr;
/* find first instance of token */
for (; i != ls->tokens.end(); ++i)
if (i->token == TK_NAME && strcmp(str, i->seminfo.ts->contents) == 0) {
ts = i->seminfo.ts;
i->token = token;
break;
}
/* find further instances of the token; faster now that we have TString */
if (ts)
for (; i != ls->tokens.end(); ++i)
if (i->token == TK_NAME && eqstr(i->seminfo.ts, ts))
i->token = token;
}

static void usestat (LexState *ls) {
luaX_next(ls); /* skip 'pluto_use' */
do {
bool is_enabled = (ls->t.token != TK_NAME);
int token = checkkeyword(ls);
bool enable = true;
if (testnext(ls, '=')) {
if (testnext(ls, TK_FALSE))
enable = false;
else checknext(ls, TK_FALSE);
}
if (is_enabled != enable) {
if (enable)
enablekeyword(ls, token);
else
disablekeyword(ls, token);
}
} while (testnext(ls, ','));

/* update ls->t */
luaX_prev(ls);
luaX_next(ls);
}


static void statement (LexState *ls, TypeDesc *prop) {
if (ls->shouldSuggest()) {
SuggestionsState ss(ls);
Expand Down Expand Up @@ -3986,9 +4048,7 @@ static void statement (LexState *ls, TypeDesc *prop) {
funcstat(ls, line);
break;
}
#ifndef PLUTO_COMPATIBLE_CLASS
case TK_CLASS:
#endif
case TK_PCLASS: {
classstat(ls);
break;
Expand All @@ -4004,19 +4064,13 @@ static void statement (LexState *ls, TypeDesc *prop) {
}
if (testnext(ls, TK_FUNCTION)) /* local function? */
localfunc(ls);
#ifdef PLUTO_COMPATIBLE_CLASS
else if (testnext(ls, TK_PCLASS))
#else
else if (testnext(ls, TK_CLASS) || testnext(ls, TK_PCLASS))
#endif
else if (testnext2(ls, TK_CLASS, TK_PCLASS))
localclass(ls);
else
localstat(ls);
break;
}
#ifndef PLUTO_COMPATIBLE_EXPORT
case TK_EXPORT:
#endif
case TK_PEXPORT: {
if (ls->fs->bl->previous)
luaX_syntaxerror(ls, "Attempt to use 'export' outside of global scope");
Expand All @@ -4033,11 +4087,7 @@ static void statement (LexState *ls, TypeDesc *prop) {
luaX_prev(ls);
localfunc(ls);
}
#ifdef PLUTO_COMPATIBLE_CLASS
else if (testnext(ls, TK_PCLASS)) {
#else
else if (testnext(ls, TK_CLASS) || testnext(ls, TK_PCLASS)) {
#endif
else if (testnext2(ls, TK_CLASS, TK_PCLASS)) {
ls->export_symbols.emplace_back(str_checkname(ls, true));
luaX_prev(ls);
localclass(ls);
Expand All @@ -4063,9 +4113,7 @@ static void statement (LexState *ls, TypeDesc *prop) {
breakstat(ls);
break;
}
#ifndef PLUTO_COMPATIBLE_CONTINUE
case TK_CONTINUE:
#endif
case TK_PCONTINUE: {
continuestat(ls);
break;
Expand All @@ -4075,20 +4123,20 @@ static void statement (LexState *ls, TypeDesc *prop) {
gotostat(ls);
break;
}
#ifndef PLUTO_COMPATIBLE_SWITCH
case TK_SWITCH:
#endif
case TK_PSWITCH: {
switchstat(ls, line);
break;
}
#ifndef PLUTO_COMPATIBLE_ENUM
case TK_ENUM:
#endif
case TK_PENUM: {
enumstat(ls);
break;
}
case TK_PUSE: {
usestat(ls);
break;
}
default: { /* stat -> func | assignment */
exprstat(ls);
break;
Expand All @@ -4111,9 +4159,7 @@ static void builtinoperators (LexState *ls) {
/* discover what operators are used */
for (const auto& t : ls->tokens) {
switch (t.token) {
#ifndef PLUTO_COMPATIBLE_NEW
case TK_NEW:
#endif
case TK_PNEW:
uses_new = true;
break;
Expand Down Expand Up @@ -4371,6 +4417,27 @@ LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
lexstate.dyd = dyd;
dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;
luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar);
#ifdef PLUTO_COMPATIBLE_SWITCH
disablekeyword(&lexstate, TK_SWITCH);
#endif
#ifdef PLUTO_COMPATIBLE_CONTINUE
disablekeyword(&lexstate, TK_CONTINUE);
#endif
#ifdef PLUTO_COMPATIBLE_ENUM
disablekeyword(&lexstate, TK_ENUM);
#endif
#ifdef PLUTO_COMPATIBLE_NEW
disablekeyword(&lexstate, TK_NEW);
#endif
#ifdef PLUTO_COMPATIBLE_CLASS
disablekeyword(&lexstate, TK_CLASS);
#endif
#ifdef PLUTO_COMPATIBLE_PARENT
disablekeyword(&lexstate, TK_PARENT);
#endif
#ifdef PLUTO_COMPATIBLE_EXPORT
disablekeyword(&lexstate, TK_EXPORT);
#endif
mainfunc(&lexstate, &funcstate);
lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs);
/* all scopes should be correctly finished */
Expand Down
12 changes: 12 additions & 0 deletions tests/basic.pluto
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,18 @@ do
assert(c == 3)
end

print "Testing pluto_use."
do
pluto_use class = false

local class = { class = "class" }
assert(class.class == "class")

pluto_use class

class Human end
end

print "Testing compatibility."
do
local a = "Hi"
Expand Down

0 comments on commit 1d395bb

Please sign in to comment.