mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-16 20:28:04 +01:00
Compare commits
5 Commits
import-str
...
import-as
| Author | SHA1 | Date | |
|---|---|---|---|
| ff9899e2e2 | |||
| 00bf53e3cb | |||
| c726f7a26c | |||
| 786e4c8ed4 | |||
| 03b44ca6f1 |
@ -42,6 +42,17 @@ if (thirsty) {
|
|||||||
}
|
}
|
||||||
</pre>
|
</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
|
If you want to load a module, but not bind any variables from it, you can omit
|
||||||
the `for` clause:
|
the `for` clause:
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -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:
|
reserves. Here's what Wren has:
|
||||||
|
|
||||||
<pre class="snippet">
|
<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
|
in is null return static super this true var while
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|||||||
@ -95,6 +95,7 @@ typedef enum
|
|||||||
TOKEN_FOREIGN,
|
TOKEN_FOREIGN,
|
||||||
TOKEN_IF,
|
TOKEN_IF,
|
||||||
TOKEN_IMPORT,
|
TOKEN_IMPORT,
|
||||||
|
TOKEN_AS,
|
||||||
TOKEN_IN,
|
TOKEN_IN,
|
||||||
TOKEN_IS,
|
TOKEN_IS,
|
||||||
TOKEN_NULL,
|
TOKEN_NULL,
|
||||||
@ -575,6 +576,7 @@ static Keyword keywords[] =
|
|||||||
{"foreign", 7, TOKEN_FOREIGN},
|
{"foreign", 7, TOKEN_FOREIGN},
|
||||||
{"if", 2, TOKEN_IF},
|
{"if", 2, TOKEN_IF},
|
||||||
{"import", 6, TOKEN_IMPORT},
|
{"import", 6, TOKEN_IMPORT},
|
||||||
|
{"as", 2, TOKEN_AS},
|
||||||
{"in", 2, TOKEN_IN},
|
{"in", 2, TOKEN_IN},
|
||||||
{"is", 2, TOKEN_IS},
|
{"is", 2, TOKEN_IS},
|
||||||
{"null", 4, TOKEN_NULL},
|
{"null", 4, TOKEN_NULL},
|
||||||
@ -2629,6 +2631,7 @@ GrammarRule rules[] =
|
|||||||
/* TOKEN_FOREIGN */ UNUSED,
|
/* TOKEN_FOREIGN */ UNUSED,
|
||||||
/* TOKEN_IF */ UNUSED,
|
/* TOKEN_IF */ UNUSED,
|
||||||
/* TOKEN_IMPORT */ UNUSED,
|
/* TOKEN_IMPORT */ UNUSED,
|
||||||
|
/* TOKEN_AS */ UNUSED,
|
||||||
/* TOKEN_IN */ UNUSED,
|
/* TOKEN_IN */ UNUSED,
|
||||||
/* TOKEN_IS */ INFIX_OPERATOR(PREC_IS, "is"),
|
/* TOKEN_IS */ INFIX_OPERATOR(PREC_IS, "is"),
|
||||||
/* TOKEN_NULL */ PREFIX(null),
|
/* TOKEN_NULL */ PREFIX(null),
|
||||||
@ -2721,7 +2724,6 @@ static int getByteCountForArguments(const uint8_t* bytecode,
|
|||||||
case CODE_FOREIGN_CONSTRUCT:
|
case CODE_FOREIGN_CONSTRUCT:
|
||||||
case CODE_FOREIGN_CLASS:
|
case CODE_FOREIGN_CLASS:
|
||||||
case CODE_END_MODULE:
|
case CODE_END_MODULE:
|
||||||
case CODE_IMPORT_MODULE:
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case CODE_LOAD_LOCAL:
|
case CODE_LOAD_LOCAL:
|
||||||
@ -2762,6 +2764,7 @@ static int getByteCountForArguments(const uint8_t* bytecode,
|
|||||||
case CODE_OR:
|
case CODE_OR:
|
||||||
case CODE_METHOD_INSTANCE:
|
case CODE_METHOD_INSTANCE:
|
||||||
case CODE_METHOD_STATIC:
|
case CODE_METHOD_STATIC:
|
||||||
|
case CODE_IMPORT_MODULE:
|
||||||
case CODE_IMPORT_VARIABLE:
|
case CODE_IMPORT_VARIABLE:
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
@ -3343,18 +3346,11 @@ static void classDefinition(Compiler* compiler, bool isForeign)
|
|||||||
static void import(Compiler* compiler)
|
static void import(Compiler* compiler)
|
||||||
{
|
{
|
||||||
ignoreNewlines(compiler);
|
ignoreNewlines(compiler);
|
||||||
|
consume(compiler, TOKEN_STRING, "Expect a string after 'import'.");
|
||||||
|
int moduleConstant = addConstant(compiler, compiler->parser->previous.value);
|
||||||
|
|
||||||
if(match(compiler, TOKEN_STRING)) {
|
|
||||||
int constant = addConstant(compiler, compiler->parser->previous.value);
|
|
||||||
emitShortArg(compiler, CODE_CONSTANT, constant);
|
|
||||||
} else if(match(compiler, TOKEN_INTERPOLATION)) {
|
|
||||||
stringInterpolation(compiler, false);
|
|
||||||
} else {
|
|
||||||
error(compiler, "Expect a string after 'import'");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the module.
|
// Load the module.
|
||||||
emitOp(compiler, CODE_IMPORT_MODULE);
|
emitShortArg(compiler, CODE_IMPORT_MODULE, moduleConstant);
|
||||||
|
|
||||||
// Discard the unused result value from calling the module body's closure.
|
// Discard the unused result value from calling the module body's closure.
|
||||||
emitOp(compiler, CODE_POP);
|
emitOp(compiler, CODE_POP);
|
||||||
@ -3366,17 +3362,38 @@ static void import(Compiler* compiler)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
ignoreNewlines(compiler);
|
ignoreNewlines(compiler);
|
||||||
int slot = declareNamedVariable(compiler);
|
|
||||||
|
|
||||||
// Define a string constant for the variable name.
|
consume(compiler, TOKEN_NAME, "Expect variable name.");
|
||||||
int variableConstant = addConstant(compiler,
|
|
||||||
wrenNewStringLength(compiler->parser->vm,
|
|
||||||
compiler->parser->previous.start,
|
|
||||||
compiler->parser->previous.length));
|
|
||||||
|
|
||||||
|
// 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.
|
// 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.
|
// Store the result in the variable here.
|
||||||
defineVariable(compiler, slot);
|
defineVariable(compiler, slot);
|
||||||
} while (match(compiler, TOKEN_COMMA));
|
} while (match(compiler, TOKEN_COMMA));
|
||||||
|
|||||||
@ -1281,7 +1281,7 @@ static WrenInterpretResult runInterpreter(WrenVM* vm, register ObjFiber* fiber)
|
|||||||
// value. It will be popped after this fiber is resumed. Store the
|
// value. It will be popped after this fiber is resumed. Store the
|
||||||
// imported module's closure in the slot in case a GC happens when
|
// imported module's closure in the slot in case a GC happens when
|
||||||
// invoking the closure.
|
// invoking the closure.
|
||||||
PUSH(importModule(vm, POP()));
|
PUSH(importModule(vm, fn->constants.data[READ_SHORT()]));
|
||||||
if (wrenHasError(fiber)) RUNTIME_ERROR();
|
if (wrenHasError(fiber)) RUNTIME_ERROR();
|
||||||
|
|
||||||
// If we get a closure, call it to execute the module body.
|
// If we get a closure, call it to execute the module body.
|
||||||
|
|||||||
11
test/language/module/import_as/import_as.wren
Normal file
11
test/language/module/import_as/import_as.wren
Normal 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
|
||||||
7
test/language/module/import_as/module.wren
Normal file
7
test/language/module/import_as/module.wren
Normal 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"
|
||||||
Reference in New Issue
Block a user