From 8ef070bf94553a87c727fec8356eb26c82c982e8 Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Mon, 4 Jan 2021 07:47:05 +0900 Subject: [PATCH] Support 'from foo import bar, baz' --- compiler.c | 18 ++++++++++++++++++ rline.c | 2 +- scanner.c | 5 ++++- scanner.h | 1 + 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/compiler.c b/compiler.c index 288b9f0..da8ca9a 100644 --- a/compiler.c +++ b/compiler.c @@ -1263,6 +1263,22 @@ static void importStatement() { defineVariable(ind); } +static void fromImportStatement() { + consume(TOKEN_IDENTIFIER, "Expected module name after 'from'"); + size_t ind = identifierConstant(&parser.previous); + EMIT_CONSTANT_OP(OP_IMPORT, ind); + consume(TOKEN_IMPORT, "Exported 'import' after module name"); + do { + consume(TOKEN_IDENTIFIER, "Expected member name"); + size_t member = identifierConstant(&parser.previous); + emitBytes(OP_DUP, 0); /* Duplicate the package object so we can GET_PROPERTY on it? */ + EMIT_CONSTANT_OP(OP_GET_PROPERTY, member); + declareVariable(); + defineVariable(member); + } while (match(TOKEN_COMMA)); + emitByte(OP_POP); /* Pop the remaining copy of the module. */ +} + static void exportStatement() { do { consume(TOKEN_IDENTIFIER, "only named variable may be exported to the global namespace"); @@ -1299,6 +1315,8 @@ static void statement() { returnStatement(); } else if (match(TOKEN_IMPORT)) { importStatement(); + } else if (match(TOKEN_FROM)) { + fromImportStatement(); } else if (match(TOKEN_BREAK)) { breakStatement(); } else if (match(TOKEN_CONTINUE)) { diff --git a/rline.c b/rline.c index 843c2bd..dbe7feb 100644 --- a/rline.c +++ b/rline.c @@ -521,7 +521,7 @@ void paint_krk_string(struct syntax_state * state, int type) { char * syn_krk_keywords[] = { "and","class","def","else","export","for","if","in","import", "let","not","or","print","return","while","try","except","raise", - "continue","break","as", + "continue","break","as","from", NULL }; diff --git a/scanner.c b/scanner.c index 461a74e..6334e27 100644 --- a/scanner.c +++ b/scanner.c @@ -208,7 +208,10 @@ static KrkTokenType identifierType() { case 'c': return checkKeyword(3, "ept", TOKEN_EXCEPT); } break; } break; - case 'f': return checkKeyword(1, "or", TOKEN_FOR); + case 'f': if (MORE(1)) switch(scanner.start[1]) { + case 'o': return checkKeyword(2, "r", TOKEN_FOR); + case 'r': return checkKeyword(2, "om", TOKEN_FROM); + } break; case 'F': return checkKeyword(1, "alse", TOKEN_FALSE); case 'i': if (MORE(1)) switch (scanner.start[1]) { case 'f': return checkKeyword(2, "", TOKEN_IF); diff --git a/scanner.h b/scanner.h index 5d8446d..c287dda 100644 --- a/scanner.h +++ b/scanner.h @@ -65,6 +65,7 @@ typedef enum { TOKEN_MINUS_MINUS,/* -- */ TOKEN_AS, + TOKEN_FROM, TOKEN_ERROR, TOKEN_EOF,