module Minjs::Lex::Function

Function

Public Instance Methods

func_declaration(var_env) click to toggle source

Tests next literal is FunctionDeclaration or not.

If literal is FunctionDeclaration return ECMA262::StFunc object and forward lexical parser position. Otherwise return nil and position is not changed.

@see www.ecma-international.org/ecma-262 ECMA262 13

@note

The function declaration in statement(block) is not permitted by ECMA262.
However, almost all implementation permit it, so minjs cannot raise
exception even if function declarataion in block.
# File lib/minjs/lex/function.rb, line 19
def func_declaration(var_env)
  # FunctionDeclaration :
  # function Identifier ( FormalParameterListopt ) { FunctionBody }
  return nil if eql_lit?(ECMA262::ID_FUNCTION).nil?

  new_var_env = ECMA262::LexEnv.new(outer: var_env)

  if id=identifier(var_env) and
    eql_lit?(ECMA262::PUNC_LPARENTHESIS) and
    args = formal_parameter_list(new_var_env) and
    eql_lit?(ECMA262::PUNC_RPARENTHESIS) and
    eql_lit?(ECMA262::PUNC_LCURLYBRAC) and
    b=func_body(new_var_env) and eql_lit?(ECMA262::PUNC_RCURLYBRAC)
    f = ECMA262::StFunc.new(new_var_env, id, args, b, {:decl => true})

    var_env.record.create_mutable_binding(id, nil)
    var_env.record.set_mutable_binding(id, f, nil)
    f
  else
    if b
      raise ParseError.new("No `}' at end of function", self)
    else
      raise ParseError.new("Bad function declaration", self)
    end
  end
end
func_exp(var_env) click to toggle source

Tests next literal is FunctionExpression or not.

If literal is FunctionExpression return ECMA262::StFunc object and forward lexical parser position. Otherwise return nil and position is not changed.

@see www.ecma-international.org/ecma-262 ECMA262 13

@note

The function expression and declaration uses same class
for convenience.
# File lib/minjs/lex/function.rb, line 59
def func_exp(var_env)
  # FunctionExpression :
  # function Identifieropt ( FormalParameterListopt ) { FunctionBody }
  return nil if eql_lit?(ECMA262::ID_FUNCTION).nil?
  @logger.debug "*** func_exp"

  id_opt = identifier(var_env)
  new_var_env = ECMA262::LexEnv.new(outer: var_env)

  if eql_lit?(ECMA262::PUNC_LPARENTHESIS) and
    args = formal_parameter_list(new_var_env) and
    eql_lit?(ECMA262::PUNC_RPARENTHESIS) and
    eql_lit?(ECMA262::PUNC_LCURLYBRAC) and
    b = func_body(new_var_env) and eql_lit?(ECMA262::PUNC_RCURLYBRAC)
    f = ECMA262::StFunc.new(new_var_env, id_opt, args, b)
    #new_var_env.func = f
    if id_opt
      var_env.record.create_mutable_binding(id_opt, nil)
      var_env.record.set_mutable_binding(id_opt, f, nil)
    end
    f
  else
    if b
      raise ParseError.new("No `}' at end of function", self)
    else
      raise ParseError.new("Bad function expression", self)
    end
  end
end

Private Instance Methods

formal_parameter_list(var_env) click to toggle source
# File lib/minjs/lex/function.rb, line 89
def formal_parameter_list(var_env)
  ret = []
  unless peek_lit(nil).eql? ECMA262::PUNC_RPARENTHESIS
    while true
      if arg = identifier(var_env)
        ret.push(arg)
      else
        raise ParseError.new("unexpceted token", self)
      end
      if peek_lit(nil).eql? ECMA262::PUNC_RPARENTHESIS
        break
      elsif eql_lit? ECMA262::PUNC_COMMA
        ;
      else
        raise ParseError.new("unexpceted token", self)
      end
    end
  end
  ret.each do |argName|
    var_env.record.create_mutable_binding(argName, nil)
    var_env.record.set_mutable_binding(argName, :undefined, nil, _parameter_list: true)
  end
  ret
end
func_body(var_env) click to toggle source
# File lib/minjs/lex/function.rb, line 114
def func_body(var_env)
  source_elements(var_env)
end