Exemple #1
0
static SymPtr FieldReference(SymPtr clas)
{
	SymPtr field,parent;
	char *fieldname;
	
	SkipToken(tPERIOD);
	fieldname = GetIdent();
	    
	/* lookup field in class and parents */
	parent=clas;
	while( parent!=NULL )
	{
		field = SymFindLocal(fieldname,parent);
		if( field!=NULL ) break;
		parent = parent->super;
	}

	if( field==NULL )
	{
		compileError("field '%s' not found",fieldname); 
		return NULL;
	}
	
	field->flags |= SYM_FIELD; /* MCC */
	
	if( field->flags&SYM_PRIVATE )
	{
		compileError("attempt to access private field '%s'",fieldname);
		return NULL;
	}
	
	if( field->flags&SYM_PROTECTED && !in_class )
	{
		compileError("attempt to access protected field '%s'",fieldname);
		return NULL;
	}

	NextToken();

	if( is_func_kind(field) )
    {
		return field;
    }
	
	if( is_global_kind(clas) )
	{
		vm_genI(op_getglobal,clas->num);
	}
	else if( is_local_kind(clas) )
	{
		vm_genI(op_getlocal,clas->num);
	}

	return field;
}
Exemple #2
0
static SymPtr LookupIdent(char **name)
{
	SymPtr sym=NULL,parent;
	
    /* check this class only */
	if( in_class && Token==tSELF )
	{
		SkipToken(tSELF);
		SkipToken(tPERIOD);
		*name = GetIdent();
		sym = SymFindLevel(*name,(SymGetScope()-1));
	}
    /* check super class only */
	else if( in_class && Token==tSUPER && base_class->super!=NULL )
	{
	    SkipToken(tSUPER);
	    SkipToken(tPERIOD);
	    *name = GetIdent();
	    sym = SymFindLocal(*name,base_class->super);
        
	    if( sym!=NULL && sym->flags&SYM_PRIVATE )
	    {
		    compileError("attempt to access private field '%s'",*name);
		    NextToken();
		    return COMPILE_ERROR;
	    }
	}
	/* check all super classes */
    else if( in_class )
	{
        *name = GetIdent();
        parent=base_class->super;
        while(parent!=NULL)
        {
            sym = SymFindLocal(*name,parent);
            if(sym!=NULL) break;
            parent=parent->super;
        }
	   	if( sym!=NULL && sym->flags&SYM_PRIVATE )
	    {
		    compileError("attempt to access private field '%s'",*name);
		    NextToken();
		    return COMPILE_ERROR;
	    }
	}
    
    /* check globals */
    if( sym==NULL )
	{
		*name = GetIdent();
		sym = SymFind(*name);
	}
    
	return sym;
}
Exemple #3
0
Int32 parse(Pointer prog,Int32 size)
{
	break_num=0;
	setlocal_num=0;
	return_num=0;
	in_class=FALSE;
	in_method=FALSE;
	cur_scope=SYM_PUBLIC;
	local_num=0;
	global_num=0;
	base_class=NULL;
	super_class=NULL;
	new_class=NULL;
	compile_error=FALSE;
	ScnInit(prog,size);
	if( Token==tERROR || Token==tEOF )
    {
        compileError("EOF detected");
    }
    else
    {
        compile_error=FALSE;
	    SymInit();
    	Program();
        SymFree();
    }

    return compile_error;
}
Exemple #4
0
static void PrivateStatement(void)
{
	SkipToken(tPRIVATE);
	cur_scope=SYM_PRIVATE;
	if(!in_class || in_method)
	{
		compileError("private only valid inside a class definition");
	}
}
Exemple #5
0
static void ProtectedStatement(void)
{
	SkipToken(tPROTECTED);
	cur_scope=SYM_PROTECTED;
	if(!in_class || in_method)
	{
		compileError("protected only valid inside a class definition");
	}
}
Exemple #6
0
static void PublicStatement(void)
{
	SkipToken(tPUBLIC);
	cur_scope=SYM_PUBLIC;	
	if(!in_class || in_method)
	{
		compileError("public only valid inside a class definition");
	}
}
Exemple #7
0
static void FunctionCall(SymPtr sym,SymPtr clas)
{
	Int32 argc;

	/* push retval */
	vm_genI(op_pushint,0);
	
	/* push args */
    argc = 0;
    if( xstrcmp(sym->name,NEW)!=0 )
    {
	    argc = ActualParams();
    }

	if( sym->nargs != -1 )
	{
		if( sym->nargs != argc )
		{
			compileError("wrong number of arguments in function call");
		}
	}

	/* push class if necessary */
	if( clas!=NULL )
	{
		argc++;
		if( is_global_kind(clas) )
		{
			vm_genI(op_getglobal,clas->num);
		}
		else if( is_local_kind(clas) )
		{
			vm_genI(op_getlocal,clas->num);
		}
	}
    else if( in_class && sym->clas!=NULL )
    {
		argc++;
    	vm_genI(op_getlocal,-2);
    }

	/* push argc */
	vm_genI(op_pushint,argc);
	
	/* call the function */
	if( sym->kind==FUNCTION_KIND )
	{
		vm_genI(op_jsr,sym->object.u.ival);
	}
	else if( sym->kind==CFUNCTION_KIND )
	{
		vm_genI(op_call,sym->index);
	}
}
Exemple #8
0
static void LibraryStatement(void)
{
	char *libname;

	SkipToken(tLIBRARY);
	
	if( Token==tSTRINGCONST )
	{
		libname=GetString();
		LibLoad(libname); /* ignored in console version */
		NextToken();
	}
	else
		compileError("expected library name");
}
ScriptErrorWidget::ScriptErrorWidget(QWidget *parent) :
    QDockWidget(parent),
    ui(new Ui::ScriptErrorWidget)
{
    ui->setupUi(this);
    connect(HilecSingleton::hilec(), SIGNAL(compileError(ScriptCompileInfo)), SLOT(updateCompileError(ScriptCompileInfo)));

    mErrorIcons[ScriptCompileProblem::Error] = QIcon(":/ProjectEditor/exclamation.png");
    mErrorIcons[ScriptCompileProblem::Warning] = QIcon(":/ProjectEditor/error.png");
    mErrorIcons[ScriptCompileProblem::Info] = QIcon(":/ProjectEditor/information.png");
    mModeEnabled[ScriptCompileProblem::Info] = false;
    mModeEnabled[ScriptCompileProblem::Warning] = true;
    mModeEnabled[ScriptCompileProblem::Error] = true;
    ui->enableErrors->setChecked(mModeEnabled[ScriptCompileProblem::Error]);
    ui->enableWarnings->setChecked(mModeEnabled[ScriptCompileProblem::Warning]);
    ui->enableInfos->setChecked(mModeEnabled[ScriptCompileProblem::Info]);
}
Exemple #10
0
bool DuckCompiler::compile(const QString &code, QByteArray *data)
{
    QStringList lines = code.split(QRegExp("\\n"));
    currentLine = 0;
    int errorCount = 0;
    int processedCount = 0;

    QString prevInstruction;
    QString prevArgument;
    foreach (QString line, lines) {
        currentLine++;
        int defaultDelay = DEFAULT_DELAY;
        int repeat = 0;
        QString cleanLine = line.trimmed();
        if (!cleanLine.isEmpty() && !cleanLine.startsWith("//")) {
            QStringList instructions = cleanLine.split(QRegExp("\\s"));
            const QString &instruction = instructions[0];
            const QString & argument = instructions.length() == 2 ? instructions[1].trimmed() : "";

            if (instruction == "REM") {
                continue;
            }

            bool ok = processInstruction(instruction, argument, data, &repeat, &defaultDelay);

            if (ok) {
                if (repeat > 0 && (prevInstruction.isEmpty() || prevInstruction == "REPEAT" || currentLine == 1)) {
                    emit compileError(currentLine, 0, QString(tr("unable to repeat previous instruction")));
                    errorCount++;
                    continue;
                }

                processedCount++;

                while (ok && repeat > 0) {
                    repeat--;
                    ok = processInstruction(prevInstruction, prevArgument, data);
                }

                prevInstruction = instruction;
                prevArgument = argument;
            } else {
                errorCount++;
            }
        }
    }
Exemple #11
0
static int compileInner(EcCompiler *cp, int argc, char **argv)
{
    Ejs         *ejs;
    EjsModule   *mp;
    MprList     *nodes;
    EjsBlock    *block;
    EcLocation  loc;
    cchar       *ext;
    char        *msg;
    int         next, i, j, nextModule, lflags, rc, paused;

    ejs = cp->ejs;
    if ((nodes = mprCreateList(-1, 0)) == 0) {
        return EJS_ERR;
    }
    cp->nodes = nodes;

    /*
        Warn about source files mentioned multiple times.
        TODO OPT. This is slow.
     */
    for (i = 0; i < argc; i++) {
        for (j = 0; j < argc; j++) {
            if (i == j) {
                continue;
            }
            if (mprSamePath(argv[i], argv[j])) {
                compileError(cp, "Loading source %s multiple times. Ignoring extra copies.", argv[i]);
                return EJS_ERR;
            }
        }
        if (cp->outputFile && mprSamePath(cp->outputFile, argv[i])) {
            compileError(cp, "Output file is the same as input file: %s", argv[i]);
            return EJS_ERR;
        }
    }

    /*
        Compile source files and load any module files
     */
    for (i = 0; i < argc && !cp->fatalError; i++) {
        ext = mprGetPathExt(argv[i]);
        if (scasecmp(ext, "mod") == 0 || scasecmp(ext, BIT_SHOBJ) == 0) {
            nextModule = mprGetListLength(ejs->modules);
            lflags = cp->strict ? EJS_LOADER_STRICT : 0;
            if ((rc = ejsLoadModule(cp->ejs, ejsCreateStringFromAsc(ejs, argv[i]), -1, -1, lflags)) < 0) {
                msg = sfmt("Error initializing module %s\n%s", argv[i], ejsGetErrorMsg(cp->ejs, 1));
                memset(&loc, 0, sizeof(EcLocation));
                loc.filename = sclone(argv[i]);
                if (rc == MPR_ERR_CANT_INITIALIZE) {
                    ecError(cp, "Error", &loc, msg);
                } else {
                    ecError(cp, "Error", &loc, msg);
                }
                cp->nodes = NULL;
                return EJS_ERR;
            }
            if (cp->merge) {
                /*
                    If merging, we must emit the loaded module into the output. So add to the compiled modules list.
                 */
                for (next = nextModule; (mp = mprGetNextItem(ejs->modules, &next)) != 0; ) {
                    if (mprLookupItem(cp->modules, mp) < 0 && mprAddItem(cp->modules, mp) < 0) {
                        compileError(cp, "Can't add module %s", mp->name);
                    }
                }
            }
            mprAddItem(nodes, 0);
        } else  {
            mprAssert(!MPR->marking);
            paused = ejsBlockGC(ejs);
            mprAddItem(nodes, ecParseFile(cp, argv[i]));
            ejsUnblockGC(ejs, paused);
        }
        mprAssert(!MPR->marking);
    }
    mprAssert(ejs->result == 0 || (MPR_GET_GEN(MPR_GET_MEM(ejs->result)) != MPR->heap->dead));


    /*
        Allocate the eval frame stack. This is used for property lookups. We have one dummy block at the top always.
     */
    block = ejsCreateBlock(ejs, 0);
    mprSetName(block, "Compiler");
    ejsPushBlock(ejs, block);
    
    /*
        Process the internal representation and generate code
     */
    paused = ejsBlockGC(ejs);
    if (!cp->parseOnly && cp->errorCount == 0) {
        ecResetParser(cp);
        if (ecAstProcess(cp) < 0) {
            ejsPopBlock(ejs);
            cp->nodes = NULL;
            ejsUnblockGC(ejs, paused);
            return EJS_ERR;
        }
        if (cp->errorCount == 0) {
            ecResetParser(cp);
            if (ecCodeGen(cp) < 0) {
                ejsPopBlock(ejs);
                cp->nodes = NULL;
                ejsUnblockGC(ejs, paused);
                return EJS_ERR;
            }
        }
    }
    ejsPopBlock(ejs);
    mprAssert(ejs->result == 0 || (MPR_GET_GEN(MPR_GET_MEM(ejs->result)) != MPR->heap->dead));

    /*
        Add compiled modules to the interpreter
     */
    for (next = 0; ((mp = (EjsModule*) mprGetNextItem(cp->modules, &next)) != 0); ) {
        ejsAddModule(cp->ejs, mp);
    }
    cp->nodes = NULL;
    ejsUnblockGC(ejs, paused);
    if (!paused) {
        mprYield(0);
    }
    mprAssert(ejs->result == 0 || (MPR_GET_GEN(MPR_GET_MEM(ejs->result)) != MPR->heap->dead));
    return (cp->errorCount > 0) ? EJS_ERR: 0;
}
Exemple #12
0
bool AssignmentThread::traditionalTaskPrepare()
{
    compileState = NoValidSourceFile;
    QDir contestantDir = QDir(Settings::sourcePath() + contestantName);
    QList<Compiler*> compilerList = settings->getCompilerList();
    
    for (int i = 0; i < compilerList.size(); i ++) {
        if (task->getCompilerConfiguration(compilerList[i]->getCompilerName()) == "disable") continue;
        QStringList filters = compilerList[i]->getSourceExtensions();
        for (int j = 0; j < filters.size(); j ++) {
            filters[j] = task->getSourceFileName() + "." + filters[j];
        }
        QStringList files = contestantDir.entryList(filters, QDir::Files);
        sourceFile = "";
        for (int j = 0; j < files.size(); j ++) {
            qint64 fileSize = QFileInfo(Settings::sourcePath() + contestantName + QDir::separator() + files[j]).size();
            if (fileSize <= settings->getFileSizeLimit() * 1024) {
                sourceFile = files[j];
                break;
            }
        }
        
        if (! sourceFile.isEmpty()) {
            QDir(Settings::temporaryPath()).mkdir(contestantName);
            QFile::copy(Settings::sourcePath() + contestantName + QDir::separator() + sourceFile,
                        Settings::temporaryPath() + contestantName + QDir::separator() + sourceFile);
            QStringList configurationNames = compilerList[i]->getConfigurationNames();
            QStringList compilerArguments = compilerList[i]->getCompilerArguments();
            QStringList interpreterArguments = compilerList[i]->getInterpreterArguments();
            QString currentConfiguration = task->getCompilerConfiguration(compilerList[i]->getCompilerName());
            for (int j = 0; j < configurationNames.size(); j ++) {
                if (configurationNames[j] == currentConfiguration) {
                    timeLimitRatio = compilerList[i]->getTimeLimitRatio();
                    memoryLimitRatio = compilerList[i]->getMemoryLimitRatio();
                    disableMemoryLimitCheck = compilerList[i]->getDisableMemoryLimitCheck();
                    environment = compilerList[i]->getEnvironment();
                    QStringList values = environment.toStringList();
                    for (int k = 0; k < values.size(); k ++) {
                        int tmp = values[k].indexOf("=");
                        QString variable = values[k].mid(0, tmp);
                        environment.insert(variable, 
                                           environment.value(variable) + ";"
                                           + QProcessEnvironment::systemEnvironment().value(variable));
                    }
                    
                    if (compilerList[i]->getCompilerType() == Compiler::Typical) {
#ifdef Q_OS_WIN32
                                executableFile = task->getSourceFileName() + ".exe";
#endif
#ifdef Q_OS_LINUX
                                executableFile = task->getSourceFileName();
#endif
                                interpreterFlag = false;
                    } else {
                        executableFile = compilerList[i]->getInterpreterLocation();
                        arguments = interpreterArguments[j];
                        arguments.replace("%s.*", sourceFile);
                        arguments.replace("%s", task->getSourceFileName());
                        interpreterFlag = true;
                    }
                    
                    if (compilerList[i]->getCompilerType() != Compiler::InterpretiveWithoutByteCode) {
                        QString arguments = compilerArguments[j];
                        arguments.replace("%s.*", sourceFile);
                        arguments.replace("%s", task->getSourceFileName());
                        QProcess *compiler = new QProcess(this);
                        compiler->setProcessChannelMode(QProcess::MergedChannels);
                        compiler->setProcessEnvironment(environment);
                        compiler->setWorkingDirectory(Settings::temporaryPath() + contestantName);
                        compiler->start(QString("\"") + compilerList[i]->getCompilerLocation() + "\" " + arguments);
                        if (! compiler->waitForStarted(-1)) {
                            compileState = InvalidCompiler;
                            delete compiler;
                            break;
                        }
                        QElapsedTimer timer;
                        timer.start();
                        bool flag = false;
                        while (timer.elapsed() < settings->getCompileTimeLimit()) {
                            if (compiler->state() != QProcess::Running) {
                                flag = true;
                                break;
                            }
                            QCoreApplication::processEvents();
                            if (stopJudging) {
                                compiler->kill();
                                delete compiler;
                                return false;
                            }
                            msleep(10);
                        }
                        if (! flag) {
                            compiler->kill();
                            compileState = CompileTimeLimitExceeded;
                        } else
                            if (compiler->exitCode() != 0) {
                                compileState = CompileError;
                                compileMessage = QString::fromLocal8Bit(compiler->readAllStandardOutput().data());
                            } else {
                                if (compilerList[i]->getCompilerType() == Compiler::Typical) {
                                    if (! QDir(Settings::temporaryPath() + contestantName).exists(executableFile)) {
                                        compileState = InvalidCompiler;
                                    } else {
                                        compileState = CompileSuccessfully;
                                    }
                                } else {
                                    QStringList filters = compilerList[i]->getBytecodeExtensions();
                                    for (int k = 0; k < filters.size(); k ++) {
                                        filters[k] = QString("*.") + filters[k];
                                    }
                                    if (QDir(Settings::temporaryPath() + contestantName)
                                            .entryList(filters, QDir::Files).size() == 0) {
                                        compileState = InvalidCompiler;
                                    } else {
                                        compileState = CompileSuccessfully;
                                    }
                                }
                            }
                        delete compiler;
                    }
                    
                    if (compilerList[i]->getCompilerType() == Compiler::InterpretiveWithoutByteCode)
                        compileState = CompileSuccessfully;
                    
                    break;
                }
            }
            break;
        }
    }
    
    if (compileState != CompileSuccessfully) {
        emit compileError(task->getTotalTimeLimit(), (int)compileState);
        return false;
    }
    
    return true;
}
Exemple #13
0
static void ClassDefinition(void)
{
	char *name;
	Int32 label,l1;
	Int32 field_num=0;
	SymPtr clas,clas_init;
	
	SkipToken(tCLASS);
	MatchToken(tCONST);
	
	name = GetIdent();
	clas = SymAdd(name);
    clas->kind = CLASS_KIND;
	NextToken();

	in_class=TRUE;
	base_class=clas;
    cur_scope=SYM_PUBLIC;
	/* clas->super=NULL; */
	/* super_class=NULL; */
	clas->super=SymFind("Object");
	super_class=clas->super;
	if( Token==tLSS )
	{
		SkipToken(tLSS);
		MatchToken(tCONST);
		name = GetIdent();
		clas->super = SymFind(name);
		if( clas->super==NULL )
		{
			compileError("super class not found");
			return;
		}
		super_class = clas->super;
		field_num = clas->super->nlocs;
		NextToken();
	}

	SymEnterScope();

	/* default class constructor prologue */
	l1 = vm_genI(op_link,0);
	clas_init = SymAdd(NEW);    
	clas_init->kind = FUNCTION_KIND;
	clas_init->object.u.ival = l1;
	clas_init->flags |= SYM_PUBLIC;

	/* class fields and functions */
	while( TokenIn(class_statements) )
	{
		if( Token==tPUBLIC )
		{
			PublicStatement();
		}
		else if( Token==tPROTECTED )
		{
			ProtectedStatement();
		}
		else if( Token==tPRIVATE )
		{
			PrivateStatement();
		}
		else if( Token==tDEF )
		{
			label = vm_genI(op_jmp,0);
			MethodDefinition();
			vm_patch(label,vm_addr());
		}
		else
		{
			local_num = field_num++;
			AssignmentStatement();
		}
			
		if( Token==tSEMI ) SkipToken(tSEMI);
			
	}
	clas->nlocs = field_num;

	/* default class constructor epilogue */
	vm_gen0(op_nop);
	vm_genI(op_rts,2);	

	SymExitScope(clas);

	/* end of class */
	in_class=FALSE;
    base_class=NULL;
    super_class=NULL;
	SkipToken(tEND);
	if( Token==tSEMI ) SkipToken(tSEMI);
}
Exemple #14
0
static Int32 Rhs(void)
{
	char *name=NULL;
	SymPtr sym,clas=NULL;

	sym = LookupIdent(&name);
	if( sym == COMPILE_ERROR )
    {
        return INT_TYPE;
    }
	
	NextToken();

	if( sym==NULL )
	{
		compileError("invalid identifier '%s'",name);
		return INT_TYPE;
	}

	/* check for field access */
	if( Token==tPERIOD )
	{
        if( in_class && !in_method )
        {
            compileError("cannot initialize fields with objects");
            return INT_TYPE;
        }
    
		clas = sym;
		sym = FieldReference(clas);
		if( sym==NULL )
        {
            return INT_TYPE;
        }
        if( xstrcmp(sym->name,NEW)==0 )
        {
            new_class = clas;
            vm_genI(op_newclass,new_class->nlocs);
            return CLASS_TYPE;
        }
	}

	switch(sym->kind)
	{
	case NIL_KIND:
		compileError("invalid type");
		break;
		
	case GLOBAL_KIND:
		vm_genI(op_getglobal,sym->num);
		break;

	case LOCAL_KIND:
		vm_genI(op_getlocal,sym->num);
		break;

	case CONSTANT_KIND:
		switch(sym->object.type)
		{
		case INT_TYPE:			
			vm_genI(op_pushint,sym->object.u.ival);
			break;
		case REAL_TYPE:
			vm_genR(op_pushreal,sym->object.u.rval);
			break;
		case STRING_TYPE:
			vm_genS(op_pushstring,sym->object.u.pval);
			break;
		default:
			/* TODO: error */
			break;
		}
		break;
		
	case FUNCTION_KIND:
	case CFUNCTION_KIND:
		FunctionCall(sym,clas);
		break;
		
	case CLASS_KIND:
		compileError("invalid type");
		break;

	case FIELD_KIND:
        CheckClassMember(sym);
		vm_genI(op_getfield,sym->num);
		break;
	}

	/* check for array access */
	if( Token==tLBRACK )
	{
		/* allow multi-dimensional arrays */
		while( Token==tLBRACK )
		{
			/* valid array is checked at runtime */
			SkipToken(tLBRACK);
			Expr();
			SkipToken(tRBRACK);
			vm_gen0(op_getarray);
		}
	}
    
	return sym->object.type;
}
Exemple #15
0
static SymPtr Lhs(void)
{
	char *name=NULL;
	SymPtr sym,clas=NULL;


	sym = LookupIdent(&name);
	if( sym==COMPILE_ERROR )
    {
		return NULL;
	}
        
	NextToken();

	/* if a field has the same name as a global, it will override */
	if( in_class && SymGetScope()==2 && sym!=NULL )
	{
		if( sym->kind==GLOBAL_KIND )
		{
			sym=NULL;
		}
	}
		
	if( sym==NULL )
	{
		sym = SymAdd(name);
		
		if( Token==tCONST )
        {
			sym->flags |= SYM_CONSTANT;
        }
		
		if( SymGetScope()==1 )
		{
			sym->kind = GLOBAL_KIND;
			sym->num = global_num++;
		}
		else
		{
			/* MCC */
			if(in_class && !in_method)
			{
				sym->kind = FIELD_KIND;
				sym->flags |= cur_scope;
				sym->clas = base_class;
			}
			else
            {
				sym->kind = LOCAL_KIND;
				sym->flags = 0;
				sym->clas = NULL;
            }

			sym->num = local_num++;
		}
		return sym;
	}

	/* check for field access */
	if( Token==tPERIOD )
	{
    	clas = sym;
		sym = FieldReference(clas);
		if( sym==NULL )
        {
			return NULL;
        }
	}

	/* check for function call */
	if( is_func_kind(sym) )
	{
        FunctionCall(sym,clas);
		vm_gen0(op_pop);
		return NULL;
	}

	/* check for array access */
	if( Token==tLBRACK )
	{
		switch(sym->kind)
		{
		case GLOBAL_KIND: 
			vm_genI(op_getglobal,sym->num);
			break;
		
		case LOCAL_KIND:  
			vm_genI(op_getlocal,sym->num);
			break;
			
		case CONSTANT_KIND:
			switch(sym->object.type)
			{
			case INT_TYPE:			
				vm_genI(op_pushint,sym->object.u.ival);
				break;
			case REAL_TYPE:
				vm_genR(op_pushreal,sym->object.u.rval);
				break;
			case STRING_TYPE:
				vm_genS(op_pushstring,sym->object.u.pval);
				break;
			default:
				/* TODO: error */
				break;
			}
			break;
		
		case FIELD_KIND:
            CheckClassMember(sym);
			vm_genI(op_getfield,sym->num);
			break;
			
		default: 
			compileError("invalid assignment");
			break;
		}

		if( Token==tLBRACK ) /* array */
    	{
			SkipToken(tLBRACK);
			Expr();
			SkipToken(tRBRACK);
            while( Token==tLBRACK )
            {
                /* handle multi-dimension arrays */
    			vm_gen0(op_getarray);
                SkipToken(tLBRACK);
                Expr();
                SkipToken(tRBRACK);
            }
			SkipToken(tEQUALS);
			Expr();
			vm_gen0(op_setarray);
			return NULL;
		}
	}
    
	return sym;
}
Exemple #16
0
static void AssignmentStatement(void)
{
    Int32 type,count;
	SymPtr sym,clas_init=NULL;
	SymPtr parents[16];

	sym = Lhs();

	if( sym==NULL )
	{
		return;
	}
    
    CheckClassMember(sym);

	SkipToken(tEQUALS);

	if(sym->flags&SYM_DEFINED)
	{
		compileError("cannot reassign constant");
		return;
	}
	else if(sym->flags&SYM_CONSTANT)
	{
		sym->flags |= SYM_DEFINED;
	}	

    /* CheckClassMember(sym); */
	
    new_class=NULL;
	type=Expr();
	
	sym->object.type = type;
		
	switch(sym->kind)
	{
	case LOCAL_KIND:
		vm_genI(op_setlocal,sym->num);
		break;
	
	case GLOBAL_KIND:
		vm_genI(op_setglobal,sym->num);
		break;

	case FIELD_KIND:
		vm_genI(op_setfield,sym->num);
		break;

	default: 
		compileError("invalid assignment");
		break;
	}

	if( type==CLASS_TYPE && new_class != NULL )
	{
        sym->clas = new_class;
  		sym->super = new_class->super;
    	sym->locals = new_class->locals;

		/* First build a list of all super classes */
		count=0;
		clas_init=sym;
		while( clas_init!=NULL )
		{
			parents[count++] = clas_init;
			clas_init = clas_init->super;
		}
		
		/* Now call all constructors in reverse order */
		count--;
		while( count>=0 )
		{
			clas_init = SymFindLocal(NEW,parents[count]);
			FunctionCall(clas_init,sym);
			vm_gen0(op_pop);
			count--;
		}

        /* call user defined constructor */
		clas_init=SymFindLocal("init",sym);
		if( clas_init!=NULL )
		{
    		if( (Token==tLPAREN && clas_init->nargs!=0) ||
                (Token!=tLPAREN && clas_init->nargs==0) )
		    {
				FunctionCall(clas_init,sym);
				vm_gen0(op_pop);
			}
		}
	}
}