Example #1
0
func (p *Parser) Parse() *tp.ScriptObject {
	script := new(tp.ScriptObject)
	// script.Name = proto.String(p.FullPath)

	if !p.RootFile || TritiumParserShowRewriterFileName {
		script.Name = proto.String(filepath.Join(p.ScriptPath, p.FileName))
	} else {
		script.Name = proto.String("__rewriter__")
	}

	stmts := tp.ListInstructions()
	defs := make([]*tp.Function, 0) // Add a new constructor in instruction.go

	// Look for the namespace directive first.
	if p.peek().Lexeme == NAMESPACE {
		p.namespaces()
	}

	for p.peek().Lexeme != EOF {
		switch p.peek().Lexeme {
		case FUNC:
			defs = append(defs, p.definition())
		case OPEN:
			p.open(false)
		default:
			stmt := p.statement()
			stmts = append(stmts, stmt)
			// need to intersperse imports with definitions
			if constants.Instruction_InstructionType_name[int32(stmt.GetType())] == "IMPORT" {
				// Make a special function stub that represents the import.
				// Need to do this because we can't mix definitions and instructions in
				// the same array.
				imp := new(tp.Function)
				imp.Name = proto.String("@import")
				imp.Description = proto.String(stmt.GetValue())
				defs = append(defs, imp)
			}
		}
	}

	if len(defs) == 0 {
		defs = nil
	}

	var line int32
	if len(stmts) == 0 {
		stmts = nil
	} else {
		line = *stmts[0].LineNumber
	}

	script.Functions = defs
	script.Root = tp.MakeBlock(stmts, line)

	// if defs == nil && p.currentNamespace() != "tritium" {
	// 	panic(fmt.Sprintf("%s: %d -- custom modules may only be declared in function definition files", p.FileName, moduleLineNum))
	// }

	return script
}
Example #2
0
func FuncStub(pkg *tp.Package, fun *tp.Function) string {
	name := null.GetString(fun.Name)
	args := ""
	for _, arg := range fun.Args {
		t := pkg.Types[int(null.GetInt32(arg.TypeId))]
		argName := null.GetString(t.Name)
		argName = argName + " %" + null.GetString(arg.Name)
		args = args + ", " + argName
	}
	if len(args) > 1 {
		args = args[2:]
	}
	returnVal := name + "(" + args + ") " + fun.ReturnTypeString(pkg) + " "
	opens := fun.OpensTypeString(pkg)
	if opens != "Base" {
		returnVal = returnVal + opens
	}
	return returnVal
}
Example #3
0
func (pkg *Package) resolveHeader(function *tp.Function) {
	returnType := null.GetString(function.ReturnType)
	if len(returnType) > 0 {
		function.ReturnTypeId = proto.Int32(int32(pkg.findTypeIndex(returnType)))
		function.ReturnType = nil
	}

	scopeType := null.GetString(function.ScopeType)
	if len(scopeType) > 0 {
		function.ScopeTypeId = proto.Int32(int32(pkg.findTypeIndex(scopeType)))
		function.ScopeType = nil
	}

	opensType := null.GetString(function.OpensType)
	if len(opensType) > 0 {
		function.OpensTypeId = proto.Int32(int32(pkg.findTypeIndex(opensType)))
		function.OpensType = nil
	}

	for _, arg := range function.Args {
		typeName := null.GetString(arg.TypeString)
		if len(typeName) > 0 {
			arg.TypeId = proto.Int32(int32(pkg.findTypeIndex(typeName)))
			arg.TypeString = nil
		}
	}
}
Example #4
0
// can't re-use the legacy native function resolver because it's a method of a
// type that provides its own helpers and contextual data, all of which would
// be too hard to reproduce
func (pkgr *Packager) resolveNativeDeclaration(f *tp.Function, path string) {
	// first we should check that the signature refers to something that actually exists
	sigStr := strings.Replace(f.Stub(pkgr.Package), ",", ".", -1)
	if whale.LookupBuiltIn(sigStr) == nil {
		panic(fmt.Sprintf("attempt to provide signature for nonexistent native function `%s` in `%s`", sigStr, path))
	}

	// now turn the type names into the appropriate numeric ids
	if returnType := f.GetReturnType(); len(returnType) > 0 {
		f.ReturnTypeId = proto.Int32(int32(pkgr.TypeMap[returnType]))
		f.ReturnType = nil
	}
	if scopeType := f.GetScopeType(); len(scopeType) > 0 {
		f.ScopeTypeId = proto.Int32(int32(pkgr.TypeMap[scopeType]))
		f.ScopeType = nil
	}
	if opensType := f.GetOpensType(); len(opensType) > 0 {
		f.OpensTypeId = proto.Int32(int32(pkgr.TypeMap[opensType]))
		f.OpensType = nil
	}
	for _, arg := range f.Args {
		if typeName := arg.GetTypeString(); len(typeName) > 0 {
			arg.TypeId = proto.Int32(int32(pkgr.TypeMap[typeName]))
			arg.TypeString = nil
		}
	}
}
Example #5
0
func (p *Parser) definition() *tp.Function {
	isSignature := false
	node := new(tp.Function)
	// functions should be injected only into the first specified namespace
	node.Namespace = proto.String(p.Defspace)

	funcLineNo := p.pop().LineNumber // pop the `@func` keyword
	contextType := ""
	if p.peek().Lexeme == TYPE {
		contextType = p.pop().Value
		if p.peek().Lexeme != DOT {
			p.error("function context and function name must be separated by '.'")
		}
		p.pop() // pop the dot
	}

	if p.peek().Lexeme != ID {
		p.error("invalid function name in definition")
	}

	funcName := p.pop().Value
	funcFile := ""

	if len(p.ScriptPath) > 0 && p.ScriptPath != "." {
		funcFile = filepath.Join(p.ScriptPath, p.FileName)
	}

	if p.peek().Lexeme != LPAREN {
		p.error("parenthesized parameter list expected in function declaration")
	}
	p.pop() // pop the lparen
	params := p.parameters(funcName)
	if len(params) == 0 {
		params = nil
	}
	p.pop() // pop the rparen

	returnType := ""
	opensType := ""
	if p.peek().Lexeme == TYPE {
		isSignature = true
		returnType = p.pop().Value
		if p.peek().Lexeme == TYPE {
			opensType = p.pop().Value
		}
	}

	node.Name = proto.String(funcName)
	if len(funcFile) > 0 {
		node.Filename = proto.String(funcFile)
	}
	node.LineNumber = proto.Int32(funcLineNo)
	node.Args = params
	node.ScopeType = proto.String(contextType)
	node.ReturnType = proto.String(returnType)
	node.OpensType = proto.String(opensType)

	if isSignature {
		if p.peek().Lexeme == LBRACE {
			p.error("body not permitted in signature for built-in " + funcName)
		}
		node.BuiltIn = proto.Bool(true)
		return node
	}
	node.BuiltIn = proto.Bool(false)
	if p.peek().Lexeme != LBRACE {
		p.error("definition for " + funcName + " is missing a body")
	}
	funcBody := &tp.Instruction{
		Type: proto.Int32(constants.Instruction_BLOCK),
		// Children: p.block(),
		// use the wrapper to get a better error message
		Children: p.function_body(*node.Name),
	}
	node.Instruction = funcBody
	return node
}
Example #6
0
func resolveDefinition(pkg *tp.Package, fun *tp.Function, path string) {
	linkingContext := linker.NewLinkingContext(pkg)

	//	pkg.Log.Infof("\t -- Resolving --\n")
	//	pkg.Log.Infof("\t\t -- function: %v\n", fun)

	// Re-uses linker's logic to resolve function definitions
	if null.GetBool(fun.BuiltIn) == false {
		typeName := null.GetString(fun.ScopeType)

		// DON'T DO THE FOLLOWING HERE -- NEED TO RESOLVE INHERITANCE FIRST
		// // Make sure we're not replacing an existing function bacause it's (currently) a security risk
		// typeID := fun.GetScopeTypeId()
		// siblingFuncs := linkingContext.FunctionsIn(typeID)
		// // println("CHECKING FOR FRATRICIDE IN", typeName)
		// _, present := siblingFuncs[fun.Stub(pkg)]
		// if present {
		// 	msg := fmt.Sprintf("Redefining an existing function is not permitted: %s", fun.Stub(pkg))
		// 	panic(msg)
		// }
		// // for name, sib := range siblingFuncs {
		// // 	println("\t", name, sib)
		// // }
		// /////////////////////////////////////////////////////////////////////////////

		if len(typeName) != 0 {
			// When I pass in functions from the inheritance resolver, they're typeId is already set
			fun.ScopeTypeId = pkg.GetProtoTypeId(fun.ScopeType)
			fun.ScopeType = nil
		}

		localScope := make(linker.LocalDef, len(fun.Args))

		//		fun.ReturnTypeId = pkg.GetProtoTypeId(fun.ReturnType)
		for _, arg := range fun.Args {
			argTypeName := arg.TypeString
			var argTypeId int

			if argTypeName != nil {
				// Similar deal. Input functions from inheritance resolution already have ids set

				arg.TypeId = pkg.GetProtoTypeId(arg.TypeString)
				//println("Processing %", null.GetString(arg.Name))
				argTypeId = pkg.GetTypeId(null.GetString(arg.TypeString))
				arg.TypeString = nil
			} else {
				argTypeId = int(null.GetInt32(arg.TypeId))
			}

			localScope[null.GetString(arg.Name)] = argTypeId
		}

		//pkg.Log.Infof("Some insitruction: %v, %s", fun.Instruction, null.GetString(fun.Name) )
		scopeTypeId := int(null.GetInt32(fun.ScopeTypeId))
		//pkg.Log.Infof("\t\t -- opening scope type : %v\n", scopeTypeId)
		returnType := linkingContext.ProcessInstructionWithLocalScope(fun.Instruction, scopeTypeId, localScope, *fun.Name, path, false)

		if linkingContext.HasErrors() {
			message := ""
			for _, msg := range linkingContext.Errors {
				message = message + "\n" + msg
			}
			panic(message)
		}

		fun.ReturnTypeId = proto.Int32(int32(returnType))
		if fun.Instruction != nil {
			fun.Instruction.IterateAll(func(ins *tp.Instruction) {
				if *ins.Type == constants.Instruction_FUNCTION_CALL {
					if null.GetString(ins.Value) == "yield" {
						fun.OpensTypeId = ins.YieldTypeId
					}
				}
			})
		}

	}
	//pkg.Log.Infof("\t\t -- done --\n")
}
Example #7
0
func (pkg *Package) resolveFunctionDescendants(fun *tp.Function) {

	// Check if this function contains any types that have descendants
	// name := fun.Stub(pkg.Package)
	// pkg.Log.Infof("Checking for inheritance on function: %v", name)

	newFun := &tp.Function{}
	inherit := false

	// Iterate over ScopeType, Arg types, return Type, opens Type

	// ScopeType

	thisTypeId := null.GetInt32(fun.ScopeTypeId)
	newType := pkg.Package.FindDescendantType(thisTypeId)

	if newType != -1 {
		if !inherit {
			// pkg.Log.Infof("\t -- ScopeType : Found ancestral type. Cloning function %v\n", null.GetString(fun.Name))
			newFun = fun.Clone().(*tp.Function)
			// pkg.Log.Infof("\t -- New fun: %v", newFun)
			inherit = true
		}
		// pkg.Log.Infof("\t -- Resetting scopeId")
		newFun.ScopeTypeId = proto.Int32(int32(newType))
	}

	// ReturnType

	thisTypeId = null.GetInt32(fun.ReturnTypeId)
	newType = pkg.Package.FindDescendantType(thisTypeId)

	if newType != -1 {
		if !inherit {
			// pkg.Log.Infof("\t -- ReturnType : Found ancestral type. Cloning function %v\n", null.GetString(fun.Name))
			newFun = fun.Clone().(*tp.Function)
			// pkg.Log.Infof("\t -- New fun: %v", newFun)
			inherit = true
		}
		// pkg.Log.Infof("\t -- Resetting returnId")
		newFun.ReturnTypeId = proto.Int32(int32(newType))
	}

	// OpensType

	thisTypeId = null.GetInt32(fun.OpensTypeId)
	newType = pkg.Package.FindDescendantType(thisTypeId)

	if newType != -1 {

		if !inherit {
			// pkg.Log.Infof("\t -- OpensType : Found ancestral type. Cloning function %v\n", null.GetString(fun.Name))
			newFun = fun.Clone().(*tp.Function)
			// pkg.Log.Infof("\t -- New fun: %v", newFun)
			inherit = true
		}
		// pkg.Log.Infof("\t -- Resetting openTypeId")
		newFun.OpensTypeId = proto.Int32(int32(newType))
	}

	// Arguments

	for index, arg := range fun.Args {
		thisTypeId = null.GetInt32(arg.TypeId)
		newType = pkg.Package.FindDescendantType(thisTypeId)

		if newType != -1 {

			if !inherit {
				// pkg.Log.Infof("\t -- ArgType : Found ancestral type. Cloning function %v\n", null.GetString(fun.Name))
				newFun = fun.Clone().(*tp.Function)
				// pkg.Log.Infof("\t -- New fun: %v", newFun)
				inherit = true
			}
			// pkg.Log.Infof("\t -- Resetting argument")
			newFun.Args[index].TypeId = proto.Int32(int32(newType))
		}

	}

	// pkg.Log.Infof("\t -- Old function: %v\n\t -- New function: %v\n", fun, newFun)

	if inherit {
		resolveDefinition(pkg.Package, newFun, "")
		pkg.Package.Functions = append(pkg.Package.Functions, newFun)
		// println("replicated", pkg.Package.GetTypeName(newFun.GetScopeTypeId()), newFun.Stub(pkg.Package))
	}

}
Example #8
0
func printFunction(f *tp.Function, indLvl int) {
	printIndent("Name -> %v", indLvl, f.GetName())
	printIndent("Description -> %v", indLvl, f.GetDescription())
	printIndent("Filename -> %v", indLvl, f.GetFilename())
	printIndent("Line Number -> %v", indLvl, f.GetLineNumber())
	printIndent("Namespace -> %v", indLvl, f.GetNamespace())
	printIndent("Scope Type Id -> %v", indLvl, f.GetScopeTypeId())
	printIndent("Scope Type -> %v", indLvl, f.GetScopeType())
	printIndent("Return Type Id -> %v", indLvl, f.GetReturnTypeId())
	printIndent("Return Type -> %v", indLvl, f.GetReturnType())
	printIndent("Opens Type Id -> %v", indLvl, f.GetOpensTypeId())
	printIndent("Opens Type -> %v", indLvl, f.GetOpensType())
	printIndent("BuiltIn -> %v", indLvl, f.GetBuiltIn())
	printIndent("Arguments:", indLvl)
	for ind, item := range f.GetArgs() {
		printIndent("Argument[%d] -> %v", indLvl, ind, item)
	}
	printIndent("Instruction:", indLvl)
	printInstruction(f.GetInstruction(), indLvl+1)
}