Skip to content

Commit

Permalink
Merge pull request #282 from Morpho-lang/kwlabels
Browse files Browse the repository at this point in the history
Allow keywords as property and method labels
  • Loading branch information
softmattertheory authored Jan 2, 2025
2 parents 2de0fb2 c50bbc3 commit 49f65d6
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 12 deletions.
8 changes: 4 additions & 4 deletions src/classes/list.c
Original file line number Diff line number Diff line change
Expand Up @@ -708,17 708,17 @@ void list_initialize(void) {
// Define list objecttype
objectlisttype=object_addtype(&objectlistdefn);

// Locate the Object class to use as the parent class of Range
// Locate the Object class to use as the parent class of List
objectstring objname = MORPHO_STATICSTRING(OBJECT_CLASSNAME);
value objclass = builtin_findclass(MORPHO_OBJECT(&objname));

// List constructor function
builtin_addfunction(LIST_CLASSNAME, list_constructor, MORPHO_FN_CONSTRUCTOR);

// Define List class
value listclass=builtin_addclass(LIST_CLASSNAME, MORPHO_GETCLASSDEFINITION(List), objclass);
object_setveneerclass(OBJECT_LIST, listclass);

// List constructor function
morpho_addfunction(LIST_CLASSNAME, "List (...)", list_constructor, MORPHO_FN_CONSTRUCTOR, NULL);

// List error messages
morpho_defineerror(LIST_ENTRYNTFND, ERROR_HALT, LIST_ENTRYNTFND_MSG);
morpho_defineerror(LIST_ADDARGS, ERROR_HALT, LIST_ADDARGS_MSG);
Expand Down
4 changes: 3 additions & 1 deletion src/classes/range.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 191,12 @@ void range_initialize(void) {
value objclass = builtin_findclass(MORPHO_OBJECT(&objname));

// Create range veneer class
builtin_addfunction(RANGE_CLASSNAME, range_constructor, MORPHO_FN_CONSTRUCTOR);
value rangeclass=builtin_addclass(RANGE_CLASSNAME, MORPHO_GETCLASSDEFINITION(Range), objclass);
object_setveneerclass(OBJECT_RANGE, rangeclass);

// Range constructor function
morpho_addfunction(RANGE_CLASSNAME, "Range (...)", range_constructor, MORPHO_FN_CONSTRUCTOR, NULL);

// Range error messages
morpho_defineerror(RANGE_ARGS, ERROR_HALT, RANGE_ARGS_MSG);
}
7 changes: 4 additions & 3 deletions src/classes/strng.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,9 314,10 @@ void string_initialize(void) {
objectstring objname = MORPHO_STATICSTRING(OBJECT_CLASSNAME);
value objclass = builtin_findclass(MORPHO_OBJECT(&objname));

// Create string veneer class
builtin_addfunction(STRING_CLASSNAME, string_constructor, MORPHO_FN_CONSTRUCTOR);

// Create String veneer class
value stringclass=builtin_addclass(STRING_CLASSNAME, MORPHO_GETCLASSDEFINITION(String), objclass);
object_setveneerclass(OBJECT_STRING, stringclass);

// String constructor function
morpho_addfunction(STRING_CLASSNAME, "String (...)", string_constructor, MORPHO_FN_CONSTRUCTOR, NULL);
}
2 changes: 1 addition & 1 deletion src/morpho.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 113,7 @@ program *morpho_newprogram(void);
void morpho_freeprogram(program *p);

/* Optimizers */
typedef bool (*optimizerfn) (program *in);
typedef bool (optimizerfn) (program *in);
void morpho_setoptimizer(optimizerfn *optimizer);

/* Virtual machine */
Expand Down
7 changes: 6 additions & 1 deletion src/support/lex.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 142,6 @@ void lex_newline(lexer *l) {
l->line ; l->posn=0;
}


/** @brief Attempts to find a matching token for the current token.
* @param[in] l The lexer in use
* @param[out] defn Type of token, if found
Expand Down Expand Up @@ -638,6 637,12 @@ void lex_setprefn(lexer *l, processtokenfn prefn) {
* Lexer public interface
* ********************************************************************** */

/** @brief Checks if a token contains a keyword */
bool lex_tokeniskeyword(lexer *l, token *tok) {
if (tok->type==TOKEN_SYMBOL) return false;
return lex_isalpha(tok->start[0]);
}

/** @brief Identifies the next token
* @param[in] l The lexer in use
* @param[out] err An error block to fill out on an error
Expand Down
4 changes: 3 additions & 1 deletion src/support/lex.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 179,6 @@ char lex_peek(lexer *l);
char lex_peekahead(lexer *l, int n);
char lex_peekprevious(lexer *l);
void lex_newline(lexer *l);

bool lex_skipshebang(lexer *l);

/* -------------------------------------------------------
Expand All @@ -203,6 202,9 @@ bool lex_matchkeywords(lexer *l);
void lex_setwhitespacefn(lexer *l, processtokenfn whitespacefn);
void lex_setprefn(lexer *l, processtokenfn prefn);

// Get information about a token
bool lex_tokeniskeyword(lexer *l, token *tok);

// Obtain the next token
bool lex(lexer *l, token *tok, error *err);

Expand Down
13 changes: 12 additions & 1 deletion src/support/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 136,13 @@ bool parse_checktokenadvance(parser *p, tokentype type) {
return true;
}

/** Checks whether the current token is a keyword */
bool parse_checktokeniskeywordadvance(parser *p) {
PARSE_CHECK(lex_tokeniskeyword(p->lex, &p->current));
PARSE_CHECK(parse_advance(p));
return true;
}

/** @brief Checks if the next token has the required type and advance if it does, otherwise generates an error.
* @param p the parser in use
* @param type type to check
Expand Down Expand Up @@ -807,6 814,9 @@ bool parse_binary(parser *p, void *out) {
if (nodetype==NODE_ASSIGN &&
parse_checktokenadvance(p, TOKEN_FUNCTION)) {
PARSE_CHECK(parse_anonymousfunction(p, &right));
} else if (nodetype==NODE_DOT &&
parse_checktokeniskeywordadvance(p)) {
PARSE_CHECK(parse_symbol(p, &right));
} else {
PARSE_CHECK(parse_precedence(p, rule->precedence (assoc == LEFT ? 1 : 0), &right));
}
Expand Down Expand Up @@ -1066,7 1076,8 @@ bool parse_functiondeclaration(parser *p, void *out) {
body=SYNTAXTREE_UNCONNECTED;

/* Function name */
if (parse_checktokenadvance(p, TOKEN_SYMBOL)) {
if (parse_checktokenadvance(p, TOKEN_SYMBOL) ||
parse_checktokeniskeywordadvance(p)) {
name=parse_tokenasstring(p);
parse_addobject(p, name);
} else {
Expand Down
16 changes: 16 additions & 0 deletions test/class/keyword_method.morpho
Original file line number Diff line number Diff line change
@@ -0,0 1,16 @@
// Ensure a class can use keywords for method labels

class A {
init(a) {
self.a = a
}

print() {
print self.a
}
}

var a = A("foo")

a.print()
// expect: foo
15 changes: 15 additions & 0 deletions test/class/keyword_property.morpho
Original file line number Diff line number Diff line change
@@ -0,0 1,15 @@
// Ensure a class can use keywords for property labels

class A {
init(a) {
self.while = a
}
}

var a = A("foo")

print a
// expect: <A>

print a.while
// expect: foo

0 comments on commit 49f65d6

Please sign in to comment.