src/SemanticAnalysis.cpp
changeset 174 e718b56aba78
parent 172 48cffae8c9e0
child 183 05571208642f
     1.1 --- a/src/SemanticAnalysis.cpp	Sun Aug 12 20:51:31 2012 -0700
     1.2 +++ b/src/SemanticAnalysis.cpp	Sat Sep 01 16:36:20 2012 -0700
     1.3 @@ -160,6 +160,11 @@
     1.4              node->accept(this);
     1.5              if (!node->decl()->type())
     1.6                  return false;
     1.7 +        } else if (statement->isFunctionTypeStatement()) {
     1.8 +            FunctionTypeStatement *node = statement->toFunctionTypeStatement();
     1.9 +            node->accept(this);
    1.10 +            if (!node->decl()->type())
    1.11 +                return false;
    1.12          }
    1.13      }
    1.14  
    1.15 @@ -880,17 +885,18 @@
    1.16  }
    1.17  
    1.18  bool
    1.19 -SemanticAnalysis::preanalyze(FunctionStatement *node)
    1.20 +SemanticAnalysis::buildFunctionArgs(AstNode *node, TokenKind kind, const FunctionSignature &sig,
    1.21 +                                    FixedArray **argsp, FixedArray **defaultsp)
    1.22  {
    1.23 -    Local<FixedArray> args(zone_, FixedArray::New(zone_, node->parameters()->length(), Heap::Tenure_Old));
    1.24 +    Local<FixedArray> args(zone_, FixedArray::New(zone_, sig.parameters()->length(), Heap::Tenure_Old));
    1.25      if (!args)
    1.26          return false;
    1.27  
    1.28      Local<FixedArray> defaults(zone_);
    1.29  
    1.30      // Apply types to arguments.
    1.31 -    for (size_t i = 0; i < node->parameters()->length(); i++) {
    1.32 -        Parameter *parameter = node->parameters()->at(i);
    1.33 +    for (size_t i = 0; i < sig.parameters()->length(); i++) {
    1.34 +        Parameter *parameter = sig.parameters()->at(i);
    1.35          
    1.36          Local<Type> type(zone_, bindType(parameter->variable()->pos(), parameter->type()));
    1.37          if (!type)
    1.38 @@ -916,7 +922,7 @@
    1.39                  return false;
    1.40              }
    1.41  
    1.42 -            if (node->fun()->isNative() && parameter->dimensions()->length() > 1) {
    1.43 +            if (kind == TOK_NATIVE && parameter->dimensions()->length() > 1) {
    1.44                  cc_.reportError(parameter->variable()->pos(), Message_MultiArrayInNative);
    1.45                  return false;
    1.46              }
    1.47 @@ -951,7 +957,7 @@
    1.48  
    1.49          if (parameter->initializer()) {
    1.50              if (!defaults) {
    1.51 -                defaults = FixedArray::New(zone_, node->parameters()->length(), Heap::Tenure_Old);
    1.52 +                defaults = FixedArray::New(zone_, sig.parameters()->length(), Heap::Tenure_Old);
    1.53                  if (!defaults)
    1.54                      return false;
    1.55              }
    1.56 @@ -964,12 +970,69 @@
    1.57          }
    1.58      }
    1.59  
    1.60 +    *argsp = args;
    1.61 +    *defaultsp = defaults;
    1.62 +
    1.63 +    return true;
    1.64 +}
    1.65 +
    1.66 +void
    1.67 +SemanticAnalysis::visit(FunctionTypeStatement *node)
    1.68 +{
    1.69 +    if (node->decl()->type())
    1.70 +        return;
    1.71 +
    1.72 +    Local<FixedArray> args(zone_);
    1.73 +    Local<FixedArray> defaults(zone_);
    1.74 +
    1.75 +    const FunctionSignature &sig= node->signature();
    1.76 +    if (!buildFunctionArgs(node,
    1.77 +                           TOK_STOCK,
    1.78 +                           sig,
    1.79 +                           args.address(),
    1.80 +                           defaults.address()))
    1.81 +    {
    1.82 +        return;
    1.83 +    }
    1.84 +
    1.85      Local<Type> returnType(zone_);
    1.86 -    if (node->returnType() ||
    1.87 +    if (sig.returnType())
    1.88 +        returnType = bindType(node->pos(), sig.returnType());
    1.89 +    else
    1.90 +        returnType = zone_->types()->getPrimitive(PrimitiveType_Int32);
    1.91 +
    1.92 +    if (!returnType)
    1.93 +        return;
    1.94 +
    1.95 +    Local<Type> funtype(zone_, zone_->types()->newFunction(returnType, args, defaults));
    1.96 +    if (!funtype)
    1.97 +        return;
    1.98 +
    1.99 +    node->decl()->setType(funtype);
   1.100 +}
   1.101 +
   1.102 +bool
   1.103 +SemanticAnalysis::preanalyze(FunctionStatement *node)
   1.104 +{
   1.105 +    Local<FixedArray> args(zone_);
   1.106 +    Local<FixedArray> defaults(zone_);
   1.107 +
   1.108 +    const FunctionSignature &sig = node->signature();
   1.109 +    if (!buildFunctionArgs(node,
   1.110 +                           node->fun()->token(),
   1.111 +                           sig,
   1.112 +                           args.address(),
   1.113 +                           defaults.address()))
   1.114 +    {
   1.115 +        return false;
   1.116 +    }
   1.117 +
   1.118 +    Local<Type> returnType(zone_);
   1.119 +    if (sig.returnType() ||
   1.120          node->hasExplicitReturn() ||
   1.121          node->fun()->isNative())
   1.122      {
   1.123 -        returnType = bindType(node->pos(), node->returnType());
   1.124 +        returnType = bindType(node->pos(), sig.returnType());
   1.125      } else {
   1.126          returnType = zone_->types()->getVoid();
   1.127      }
   1.128 @@ -1118,6 +1181,14 @@
   1.129          return false;
   1.130      }
   1.131  
   1.132 +    if (given->isFunction() && actual->isFunction()) {
   1.133 +        if (!Type::Compare(given, actual)) {
   1.134 +            typeMismatch(pos, actual, given);
   1.135 +            return false;
   1.136 +        }
   1.137 +        return true;
   1.138 +    }
   1.139 +
   1.140      if (actual->isEnum()) {
   1.141          if (!given->isEnum() || actual != given) {
   1.142              typeMismatch(pos, actual, given);
   1.143 @@ -1199,12 +1270,11 @@
   1.144          return;
   1.145      }
   1.146  
   1.147 -    // Currently, only calls from a NameProxy are possible.
   1.148 -    NamedFunction *fun = node->callee()->toNameProxy()->binding()->toNamedFunction();
   1.149 -    if (fun->isForward()) {
   1.150 -        cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
   1.151 -        return;
   1.152 -    }
   1.153 +    // NamedFunction *fun = node->callee()->toNameProxy()->binding()->toNamedFunction();
   1.154 +    // if (fun->isForward()) {
   1.155 +    //     cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
   1.156 +    //     return;
   1.157 +    // }
   1.158  
   1.159      for (unsigned i = 0; i < node->arguments()->length(); i++) {
   1.160          // Note: we don't compute references unless the callee needs a
   1.161 @@ -1252,7 +1322,7 @@
   1.162              scope_->setUsesLifoHeap();
   1.163      }
   1.164  
   1.165 -    node->setType(fun->type()->returnType());
   1.166 +    node->setType(type->returnType());
   1.167  }
   1.168  
   1.169  void