Beispiel #1
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
		}
	}
}
Beispiel #2
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
		}
	}
}
Beispiel #3
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
}