private BoundIf BuildSetWithScope(BlockBuilder builder, WithScope withScope, IIdentifier fallback, BoundTemporary value) { var withLocal = builder.CreateTemporary(); builder.Add(new BoundSetVariable( withLocal, new BoundGetVariable(_withIdentifiers[withScope.Identifier]), SourceLocation.Missing )); var setter = new BoundSetMember( new BoundGetVariable(withLocal), BoundConstant.Create(fallback.Name), new BoundGetVariable(value), SourceLocation.Missing ); BoundBlock @else; if (withScope.Parent == null) { @else = BuildBlock(BuildSet( fallback, new BoundGetVariable(value) )); } else { @else = BuildBlock(BuildSetWithScope( builder, withScope.Parent, fallback, value )); } return new BoundIf( new BoundHasMember( new BoundGetVariable(withLocal), fallback.Name ), BuildBlock(setter), @else, SourceLocation.Missing ); }
private BoundIf BuildGetWithScope(BlockBuilder builder, WithScope withScope, IIdentifier fallback, BoundTemporary result, BoundTemporary withTarget) { var withLocal = builder.CreateTemporary(); builder.Add(new BoundSetVariable( withLocal, new BoundGetVariable(_withIdentifiers[withScope.Identifier]), SourceLocation.Missing )); var getter = new BlockBuilder(this); if (withTarget != null) { getter.Add(new BoundSetVariable( withTarget, new BoundGetVariable(withLocal), SourceLocation.Missing )); } getter.Add(new BoundSetVariable( result, BuildGetMember( new BoundGetVariable(withLocal), BoundConstant.Create(fallback.Name) ), SourceLocation.Missing )); BoundBlock @else; if (withScope.Parent == null) { @else = BuildBlock(new BoundSetVariable( result, BuildGet( fallback, null ), SourceLocation.Missing )); } else { @else = BuildBlock(BuildGetWithScope( builder, withScope.Parent, fallback, result, withTarget )); } return new BoundIf( new BoundHasMember( new BoundGetVariable(withLocal), fallback.Name ), getter.BuildBlock(SourceLocation.Missing), @else, SourceLocation.Missing ); }
private BoundStatement BuildSet(IIdentifier identifier, BoundExpression value) { switch (identifier.Type) { case IdentifierType.Parameter: return new BoundSetVariable( _scope.GetArgument(identifier), value, SourceLocation.Missing ); case IdentifierType.Scoped: var builder = new BlockBuilder(this); var valueTemporary = builder.CreateTemporary(); builder.Add(new BoundSetVariable( valueTemporary, value, SourceLocation.Missing )); builder.Add(BuildSetWithScope(builder, identifier.WithScope, identifier.Fallback, valueTemporary)); return builder.BuildBlock(SourceLocation.Missing); case IdentifierType.Local: case IdentifierType.Global: if (identifier.Type == IdentifierType.Global) _scope.IsGlobalScopeReferenced = true; if (identifier.Closure == null) return new BoundSetVariable(_scope.GetLocal(identifier), value, SourceLocation.Missing); return new BoundSetVariable( _scope.GetClosureField(identifier), value, SourceLocation.Missing ); /* // These are handled upstream. case IdentifierType.This: case IdentifierType.Null: case IdentifierType.Undefined: case IdentifierType.Arguments: */ default: throw new InvalidOperationException("Cannot find variable of argument"); } }
private BoundExpression BuildGet(IIdentifier identifier, BoundTemporary withTarget) { switch (identifier.Type) { case IdentifierType.Null: return new BoundGetVariable(BoundMagicVariable.Null); case IdentifierType.Undefined: return new BoundGetVariable(BoundMagicVariable.Undefined); case IdentifierType.This: _scope.IsThisReferenced = true; return new BoundGetVariable(BoundMagicVariable.This); case IdentifierType.Arguments: _scope.IsArgumentsReferenced = true; return new BoundGetVariable(BoundMagicVariable.Arguments); case IdentifierType.Parameter: return new BoundGetVariable(_scope.GetArgument(identifier)); case IdentifierType.Scoped: var builder = new BlockBuilder(this); var result = builder.CreateTemporary(); builder.Add( BuildGetWithScope(builder, identifier.WithScope, identifier.Fallback, result, withTarget) ); return builder.BuildExpression(result, SourceLocation.Missing); case IdentifierType.Local: case IdentifierType.Global: if (identifier.Closure != null) return new BoundGetVariable(_scope.GetClosureField(identifier)); return new BoundGetVariable(_scope.GetLocal(identifier)); default: throw new InvalidOperationException("Cannot find variable of argument"); } }