blob: 2e4c4b70f1341f22ab17d6fb36f6e42851bbc4e6 [file] [log] [blame]
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/ast_printer.h"
#include "vm/class_finalizer.h"
#include "vm/longjump.h"
#include "vm/object.h"
#include "vm/parser.h"
#include "vm/symbols.h"
#include "vm/unit_test.h"
namespace dart {
void DumpFunction(const Library& lib, const char* cname, const char* fname) {
const String& classname = String::Handle(Symbols::New(cname));
Class& cls = Class::Handle(lib.LookupClass(classname));
EXPECT(!cls.IsNull());
String& funcname = String::Handle(String::New(fname));
Function& function = Function::ZoneHandle(cls.LookupStaticFunction(funcname));
EXPECT(!function.IsNull());
bool retval;
Isolate* isolate = Isolate::Current();
EXPECT(isolate != NULL);
LongJump* base = isolate->long_jump_base();
LongJump jump;
isolate->set_long_jump_base(&jump);
if (setjmp(*jump.Set()) == 0) {
ParsedFunction* parsed_function = new ParsedFunction(function);
Parser::ParseFunction(parsed_function);
EXPECT(parsed_function->node_sequence() != NULL);
printf("Class %s function %s:\n", cname, fname);
AstPrinter::PrintFunctionNodes(*parsed_function);
retval = true;
} else {
retval = false;
}
EXPECT(retval);
isolate->set_long_jump_base(base);
}
void CheckField(const Library& lib,
const char* class_name,
const char* field_name,
bool expect_static,
bool is_final) {
const String& classname = String::Handle(Symbols::New(class_name));
Class& cls = Class::Handle(lib.LookupClass(classname));
EXPECT(!cls.IsNull());
String& fieldname = String::Handle(String::New(field_name));
String& functionname = String::Handle();
Function& function = Function::Handle();
Field& field = Field::Handle();
if (expect_static) {
field ^= cls.LookupStaticField(fieldname);
functionname ^= Field::GetterName(fieldname);
function ^= cls.LookupStaticFunction(functionname);
EXPECT(function.IsNull());
functionname ^= Field::SetterName(fieldname);
function ^= cls.LookupStaticFunction(functionname);
EXPECT(function.IsNull());
} else {
field ^= cls.LookupInstanceField(fieldname);
functionname ^= Field::GetterName(fieldname);
function ^= cls.LookupDynamicFunction(functionname);
EXPECT(!function.IsNull());
functionname ^= Field::SetterName(fieldname);
function ^= cls.LookupDynamicFunction(functionname);
EXPECT(is_final ? function.IsNull() : !function.IsNull());
}
EXPECT(!field.IsNull());
EXPECT_EQ(field.is_static(), expect_static);
}
void CheckFunction(const Library& lib,
const char* class_name,
const char* function_name,
bool expect_static) {
const String& classname = String::Handle(Symbols::New(class_name));
Class& cls = Class::Handle(lib.LookupClass(classname));
EXPECT(!cls.IsNull());
String& functionname = String::Handle(String::New(function_name));
Function& function = Function::Handle();
if (expect_static) {
function ^= cls.LookupStaticFunction(functionname);
} else {
function ^= cls.LookupDynamicFunction(functionname);
}
EXPECT(!function.IsNull());
}
TEST_CASE(ParseClassDefinition) {
const char* script_chars =
"class C { } \n"
"class A { \n"
" var f0; \n"
" int f1; \n"
" final f2; \n"
" final int f3, f4; \n"
" static String s1, s2; \n"
" static const int s3 = 8675309; \n"
" static bar(i, [var d = 5]) { return 77; } \n"
" static foo() native \"native_function_name\"; \n"
"} \n";
String& url = String::Handle(String::New("dart-test:Parser_TopLevel"));
String& source = String::Handle(String::New(script_chars));
Script& script = Script::Handle(Script::New(url,
source,
RawScript::kScriptTag));
Library& lib = Library::ZoneHandle(Library::CoreLibrary());
script.Tokenize(String::Handle(String::New("")));
Parser::ParseCompilationUnit(lib, script);
EXPECT(ClassFinalizer::FinalizePendingClasses());
CheckField(lib, "A", "f1", false, false);
CheckField(lib, "A", "f2", false, true);
CheckField(lib, "A", "f3", false, true);
CheckField(lib, "A", "f4", false, true);
CheckField(lib, "A", "s1", true, false);
CheckField(lib, "A", "s2", true, false);
CheckField(lib, "A", "s3", true, true);
CheckFunction(lib, "A", "bar", true);
CheckFunction(lib, "A", "foo", true);
}
TEST_CASE(Parser_TopLevel) {
const char* script_chars =
"class A extends B { \n"
" static bar(var i, [var d = 5]) { return 77; } \n"
" static foo() { return 42; } \n"
" static baz(var i) { var q = 5; return i + q; } \n"
"} \n"
" \n"
"class B { \n"
" static bam(k) { return A.foo(); } \n"
"} \n";
String& url = String::Handle(String::New("dart-test:Parser_TopLevel"));
String& source = String::Handle(String::New(script_chars));
Script& script = Script::Handle(Script::New(url,
source,
RawScript::kScriptTag));
Library& lib = Library::ZoneHandle(Library::CoreLibrary());
script.Tokenize(String::Handle(String::New("")));
Parser::ParseCompilationUnit(lib, script);
EXPECT(ClassFinalizer::FinalizePendingClasses());
DumpFunction(lib, "A", "foo");
DumpFunction(lib, "A", "bar");
DumpFunction(lib, "A", "baz");
DumpFunction(lib, "B", "bam");
}
} // namespace dart