use of dyvilx.tools.compiler.ast.field.Variable in project Dyvil by Dyvil.
the class OptionalChainAware method nullCoalescing.
static IValue nullCoalescing(IValue lhs, IValue rhs) {
BindingIfStatement bindingIf;
if (lhs instanceof BindingIfStatement && (bindingIf = (BindingIfStatement) lhs).getElse() == NullValue.NULL) {
// safe bet that the rhs used to be an optional chain
// this branch is actually an optimization and technically not necessary, but it is very common
// to use the null coalescing operator after an optional chain.
final IValue then = bindingIf.getThen();
if (NullableType.isNullable(then.getType())) {
// Perform the following transformation:
// if let $0 = oldReceiver { $0.oldAccess } else null
// becomes
// if (let $0 = oldReceiver, let $1 = $0.oldAccess) { $1 } else { <rhs> }
final Variable var = newVar(bindingIf.getPosition(), then);
bindingIf.addVariable(var);
bindingIf.setThen(new FieldAccess(var));
}
// if the then branch of the old binding if is not nullable, we simply set the rhs
bindingIf.setElse(rhs);
return bindingIf;
}
// the lhs was not an optional chain, so we set up an impromptu null coalescing inline implementation
final SourcePosition position = lhs.getPosition();
// let l = <lhs>
final Variable var = newVar(position, lhs);
// if let l = <lhs> { l } else { <rhs> }
bindingIf = new BindingIfStatement(position);
bindingIf.addVariable(var);
bindingIf.setThen(new FieldAccess(var));
bindingIf.setElse(rhs);
return bindingIf;
}
use of dyvilx.tools.compiler.ast.field.Variable in project Dyvil by Dyvil.
the class OptionalChainAware method newVar.
/**
* Creates a new variable for use in binding if statements. The lhs automatically gets wrapped in an optional unwrap
* operator.
*/
static Variable newVar(SourcePosition position, IValue lhs) {
final IValue value = new OptionalUnwrapOperator(lhs, true);
final Variable var = new Variable(position, null, value.getType(), AttributeList.of(Modifiers.FINAL));
var.setValue(value);
return var;
}
use of dyvilx.tools.compiler.ast.field.Variable in project Dyvil by Dyvil.
the class BraceAccessExpr method resolve.
@Override
public IValue resolve(MarkerList markers, IContext context) {
if (this.value != null) {
this.value = this.value.resolve(markers, context);
} else {
this.value = context.resolveImplicit(null);
}
if (this.value == null) {
markers.add(Markers.semanticError(this.position, "braceaccess.invalid"));
} else {
final IType valueType = this.value.getType();
final IValue typedValue = this.value.withType(valueType, valueType, markers, context);
if (typedValue != null) {
this.value = typedValue;
}
this.variable = new Variable(Names.$0, this.value.getType());
this.implicitAccess = new FieldAccess(this.variable);
}
context = context.push(this);
this.statement = this.statement.resolve(markers, context);
context.pop();
return this;
}
use of dyvilx.tools.compiler.ast.field.Variable in project Dyvil by Dyvil.
the class SideEffectHelper method processValue.
public IValue processValue(IValue value) {
if (value == null || !value.hasSideEffects()) {
return value;
}
if (this.statementList == null) {
this.statementList = new StatementList();
}
final Variable variable = new Variable(value.getPosition(), Name.fromRaw("sideEffect$" + this.registered), value.getType());
variable.setValue(value);
this.statementList.add(new VariableStatement(variable));
this.statementList.addVariable(variable);
this.registered++;
return new FieldAccess(value.getPosition(), null, variable);
}
use of dyvilx.tools.compiler.ast.field.Variable in project Dyvil by Dyvil.
the class ForDirectiveParser method parse.
@Override
public void parse(IParserManager pm, IToken token) {
// #for (IDENTIFIER <- EXPRESSION) {BLOCK}
final int type = token.type();
switch(this.mode) {
case FOR:
assert type == GenSrcSymbols.FOR;
this.mode = OPEN_PAREN;
this.directive = new ForEachDirective(token.raw(), null);
return;
case OPEN_PAREN:
if (type != BaseSymbols.OPEN_PARENTHESIS) {
pm.report(token, "for.open_paren");
this.list.add(this.directive);
pm.popParser(true);
return;
}
this.mode = VAR_NAME;
return;
case VAR_NAME:
if (type == Tokens.LETTER_IDENTIFIER) {
this.directive.setVariable(new Variable(token.raw(), token.nameValue(), Types.UNKNOWN));
this.mode = TYPE_ASCRIPTION;
return;
}
pm.report(token, "for.identifier");
if (type == BaseSymbols.CLOSE_PARENTHESIS) {
this.mode = BODY;
}
return;
case TYPE_ASCRIPTION:
if (type == BaseSymbols.COLON) {
pm.pushParser(new TypeParser(this.directive.getVariable()));
this.mode = ARROW;
return;
}
// Fallthrough
case ARROW:
if (type != GenSrcSymbols.ARROW_LEFT) {
pm.reparse();
pm.report(token, "for.arrow_left");
}
pm.pushParser(new ExpressionParser(this.directive.getVariable()));
this.mode = CLOSE_PAREN;
return;
case CLOSE_PAREN:
if (type != BaseSymbols.CLOSE_PARENTHESIS) {
pm.report(token, "for.close_paren");
return;
}
this.mode = BODY;
return;
case BODY:
if (type != BaseSymbols.OPEN_CURLY_BRACKET) {
pm.report(token, "for.open_brace");
this.list.add(this.directive);
pm.popParser(true);
return;
}
final StatementList body = new StatementList();
pm.pushParser(new BlockParser(body));
this.directive.setAction(body);
this.mode = BODY_END;
return;
case BODY_END:
if (type != BaseSymbols.CLOSE_CURLY_BRACKET) {
pm.report(token, "for.close_brace");
}
this.list.add(this.directive);
pm.popParser();
}
}
Aggregations