/** * Copyright 2005-2007 Xue Yong Zhi, Yu Su, Ye Zheng * Distributed under the BSD License */ package com.xruby.compiler.codedom; import java.util.*; public class Block { private CompoundStatement bodyStatement_ = null; private ArrayList parameters_ = new ArrayList(); private ParameterVariableExpression asterisk_parameter_ = null; private boolean asterisk = false; private ArrayList default_parameters_ = new ArrayList(); private boolean should_validate_argument_length_ = false; private boolean is_for_in_expression_ = false; private boolean has_extra_comma_ = false; private int saved_as_pulled_ = -1; private String name_ = null; private int startPosition; private int endPosition; public void setHasExtraComma() { has_extra_comma_ = true; } public void initAllParametersToNil(CodeVisitor visitor) { for (ParameterVariableExpression var : parameters_) { var.acceptAsInitializeToNil(visitor); } if (null != asterisk_parameter_) { asterisk_parameter_.acceptAsInitializeToNil(visitor); } } void getNewlyAssignedVariables(ISymbolTable symboltable, ArrayList result) { for (ParameterVariableExpression var : parameters_) { if (var instanceof LocalVariableExpression) { String name = ((LocalVariableExpression)var).getValue(); if (!symboltable.isDefinedInCurrentScope(name)) { result.add(name); } } } if (null != asterisk_parameter_) { if (asterisk_parameter_ instanceof LocalVariableExpression) { String name = ((LocalVariableExpression)asterisk_parameter_).getValue(); if (!symboltable.isDefinedInCurrentScope(name)) { result.add(name); } } } } public void setBody(CompoundStatement bodyStatement) { bodyStatement_ = bodyStatement; } public void addParameter(ParameterVariableExpression name, Expression default_value) { parameters_.add(name); if (null != default_value) { default_parameters_.add(default_value); } } void setIsForInExpression() { is_for_in_expression_ = true; } //{||} -> true //{|x,...|} -> true //{} -> false public void setShouldValidateArgumentLength() { should_validate_argument_length_ = true; } public void setAsteriskParameter(ParameterVariableExpression name) { assert(null == asterisk_parameter_); asterisk_parameter_ = name; asterisk = true; } public void setAsterisk() { this.asterisk = true; } private ArrayList buildLhs() { ArrayList mlhs = new ArrayList(); for (ParameterVariableExpression var : parameters_) { mlhs.add(var); } return mlhs; } public void acceptAsPulled(CodeVisitor visitor) { if (null != name_) { //has been pulled return; } StringBuilder name = new StringBuilder(); saved_as_pulled_ = visitor.visitBlockBegin(name, true); name_ = name.toString(); } public String accept(CodeVisitor visitor) { // f{|x, |} = f{|x, *|} if (this.asterisk && this.asterisk_parameter_ == null) { this.has_extra_comma_ = true; } if (null == name_) { //not pulled StringBuilder name = new StringBuilder(); saved_as_pulled_ = visitor.visitBlockBegin(name, false); name_ = name.toString(); } boolean has_body = null != bodyStatement_; visitor.visitBlockBodyBegin(name_, getArgc(), asterisk, default_parameters_.size(), is_for_in_expression_, has_extra_comma_, has_body); if (has_body) { boolean is_multi_rhs = (parameters_.size() > 1) || asterisk || is_for_in_expression_ || has_extra_comma_; MultipleAssignmentStatement.acceptMLhs(visitor, buildLhs(), asterisk_parameter_, has_extra_comma_, is_multi_rhs); visitor.visitTerminal(); // TODO support default_value visitor.visitBlockBody(); bodyStatement_.accept(visitor); setEndPosition(bodyStatement_.getLastLine()); } else { setEndPosition(startPosition); } visitor.visitBlockBodyEnd(name_, (has_body) ? bodyStatement_.lastStatementHasReturnValue() : false, saved_as_pulled_); if (name_ != null) { BlockFarm.markBlock(this); } return name_; } private int getArgc() { return should_validate_argument_length_ ? parameters_.size() : -1; } public int getStartPosition() { return startPosition; } public void setStartPosition(int startPosition) { this.startPosition = startPosition; } public int getEndPosition() { return endPosition; } public String getName() { return name_; } public void setEndPosition(int endPosition) { this.endPosition = endPosition; } }