[0.4.0] Import as (#775)

* Add import "..." for Variable as OtherName
This commit is contained in:
ruby
2020-12-03 09:34:36 -08:00
committed by GitHub
parent 6bd2f810e2
commit 3e0f71b742
6 changed files with 63 additions and 10 deletions

View File

@ -42,6 +42,17 @@ if (thirsty) {
}
</pre>
If you need to import a variable under a different name, you can use
`import "..." for Name as OtherName`. This looks up the top-level variable
`Name` in *that* module, but declares a variable called `OtherName` in *this* module
with its value.
<pre class="snippet">
import "liquids" for Water //Water is now taken
import "beverages" for Coffee, Water as H2O, Tea
// var water = H2O.new()
</pre>
If you want to load a module, but not bind any variables from it, you can omit
the `for` clause:

File diff suppressed because one or more lines are too long

View File

@ -43,7 +43,7 @@ One way to get a quick feel for a language's style is to see what words it
reserves. Here's what Wren has:
<pre class="snippet">
break class construct else false for foreign if import
as break class construct else false for foreign if import
in is null return static super this true var while
</pre>

View File

@ -96,6 +96,7 @@ typedef enum
TOKEN_FOREIGN,
TOKEN_IF,
TOKEN_IMPORT,
TOKEN_AS,
TOKEN_IN,
TOKEN_IS,
TOKEN_NULL,
@ -577,6 +578,7 @@ static Keyword keywords[] =
{"foreign", 7, TOKEN_FOREIGN},
{"if", 2, TOKEN_IF},
{"import", 6, TOKEN_IMPORT},
{"as", 2, TOKEN_AS},
{"in", 2, TOKEN_IN},
{"is", 2, TOKEN_IS},
{"null", 4, TOKEN_NULL},
@ -2632,6 +2634,7 @@ GrammarRule rules[] =
/* TOKEN_FOREIGN */ UNUSED,
/* TOKEN_IF */ UNUSED,
/* TOKEN_IMPORT */ UNUSED,
/* TOKEN_AS */ UNUSED,
/* TOKEN_IN */ UNUSED,
/* TOKEN_IS */ INFIX_OPERATOR(PREC_IS, "is"),
/* TOKEN_NULL */ PREFIX(null),
@ -3378,17 +3381,38 @@ static void import(Compiler* compiler)
do
{
ignoreNewlines(compiler);
int slot = declareNamedVariable(compiler);
// Define a string constant for the variable name.
int variableConstant = addConstant(compiler,
wrenNewStringLength(compiler->parser->vm,
compiler->parser->previous.start,
compiler->parser->previous.length));
consume(compiler, TOKEN_NAME, "Expect variable name.");
// We need to hold onto the source variable,
// in order to reference it in the import later
Token sourceVariableToken = compiler->parser->previous;
// Define a string constant for the original variable name.
int sourceVariableConstant = addConstant(compiler,
wrenNewStringLength(compiler->parser->vm,
sourceVariableToken.start,
sourceVariableToken.length));
// Store the symbol we care about for the variable
int slot = -1;
if(match(compiler, TOKEN_AS))
{
//import "module" for Source as Dest
//Use 'Dest' as the name by declaring a new variable for it.
//This parses a name after the 'as' and defines it.
slot = declareNamedVariable(compiler);
}
else
{
//import "module" for Source
//Uses 'Source' as the name directly
slot = declareVariable(compiler, &sourceVariableToken);
}
// Load the variable from the other module.
emitShortArg(compiler, CODE_IMPORT_VARIABLE, variableConstant);
emitShortArg(compiler, CODE_IMPORT_VARIABLE, sourceVariableConstant);
// Store the result in the variable here.
defineVariable(compiler, slot);
} while (match(compiler, TOKEN_COMMA));

View File

@ -0,0 +1,11 @@
var Module = "from here"
var ValueC = "value C"
import "./module" for ValueA, Module as Another, ValueB // expect: ran module
import "./module" for ValueC as OtherC
System.print(Module) // expect: from here
System.print(Another) // expect: from module
System.print(ValueA) // expect: module A
System.print(ValueB) // expect: module B
System.print(ValueC) // expect: value C
System.print(OtherC) // expect: module C

View File

@ -0,0 +1,7 @@
// nontest
var Module = "from module"
System.print("ran module")
var ValueA = "module A"
var ValueB = "module B"
var ValueC = "module C"