           lit = new Literal ref.name.value + ' == null'
           val = new Assign new Value(param.name), param.value, '='
           exprs.push new If lit, val
-      vars.push ref unless splats
+      params.push ref unless splats
     wasEmpty = @body.isEmpty()
     exprs.unshift splats if splats
     @body.expressions.unshift exprs... if exprs.length
-    o.scope.parameter vars[i] = v.compile o for v, i in vars unless splats
+    o.scope.parameter params[i] = p.compile o for p, i in params
+    uniqs = []
+    for name in @paramNames()
+      throw SyntaxError "multiple parameters named '#{name}'" if name in uniqs
+      uniqs.push name
     @body.makeReturn() unless wasEmpty or @noReturn
     if @bound
       if o.scope.parent.method?.bound

    node = @name
    if node.this
      node = node.properties[0].name
      node = new Literal '_' + node.value if node.value.reserved
    else if node.isComplex()
      node = new Literal o.scope.freeVariable 'arg'
    node = new Value node

    idt   = o.indent
    code  = 'function'
    code  += ' ' + @name if @ctor
    code  += '(' + params.join(', ') + ') {'
    code  += "\n#{ @body.compileWithDeclarations o }\n#{@tab}" unless @body.isEmpty()
    code  += '}'
    return @tab + code if @ctor
    if @front or (o.level >= LEVEL_ACCESS) then "(#{code})" else code

  # A list of parameter names, excluding those generated by the compiler.
  paramNames: ->
    names = []
    names.push param.names()... for param in @params
    names

  # Short-circuit `traverseChildren` method to prevent it from crossing scope boundaries
  # unless `crossScope` is `true`.
