示例#1
0
func (b *block) exit() {
	if b.outer == nil {
		log.Crash("Cannot exit top-level block")
	}
	if b.outer.scope == b.scope {
		if b.outer.inner != b {
			log.Crash("Already exited block")
		}
		if b.inner != nil && b.inner.scope == b.scope {
			log.Crash("Exit of parent block without exit of child block")
		}
	}
	b.outer.inner = nil
}
示例#2
0
// Go invokes the function asynchronously.  It returns the Call structure representing
// the invocation.  The done channel will signal when the call is complete by returning
// the same Call object.  If done is nil, Go will allocate a new channel.
// If non-nil, done must be buffered or Go will deliberately crash.
func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call {
	c := new(Call)
	c.ServiceMethod = serviceMethod
	c.Args = args
	c.Reply = reply
	if done == nil {
		done = make(chan *Call, 10) // buffered.
	} else {
		// If caller passes done != nil, it must arrange that
		// done has enough buffer for the number of simultaneous
		// RPCs that will be using that channel.  If the channel
		// is totally unbuffered, it's best not to run at all.
		if cap(done) == 0 {
			log.Crash("rpc: done channel is unbuffered")
		}
	}
	c.Done = done
	if client.shutdown != nil {
		c.Error = client.shutdown
		_ = c.Done <- c // do not block
		return c
	}
	client.send(c)
	return c
}
示例#3
0
// Publish declares an named exported variable. This should be called from a
// package's init function when it creates its Vars. If the name is already
// registered then this will log.Crash.
func Publish(name string, v Var) {
	mutex.Lock()
	defer mutex.Unlock()
	if _, existing := vars[name]; existing {
		log.Crash("Reuse of exported var name:", name)
	}
	vars[name] = v
}
示例#4
0
func (b *block) ChildScope() *Scope {
	if b.inner != nil && b.inner.scope == b.scope {
		log.Crash("Failed to exit child block before entering a child scope")
	}
	sub := b.enterChild()
	sub.offset = 0
	sub.scope = &Scope{sub, 0}
	return sub.scope
}
示例#5
0
文件: logger.go 项目: COTOHA/gorrdpd
func (logger *base) Add(severity Severity, format string, v ...interface{}) {
	if logger.addFunc == nil {
		log.Crash("Tried to use base logger, which has no ability to output. Use descendants instead!")
	}

	if severity < logger.LogLevel {
		return
	}
	logger.addFunc(severity, format, v)
}
示例#6
0
func (a *stmtCompiler) compileDeclStmt(s *ast.DeclStmt) {
	switch decl := s.Decl.(type) {
	case *ast.BadDecl:
		// Do nothing.  Already reported by parser.
		a.silentErrors++

	case *ast.FuncDecl:
		if !a.block.global {
			log.Crash("FuncDecl at statement level")
		}

	case *ast.GenDecl:
		if decl.Tok == token.IMPORT && !a.block.global {
			log.Crash("import at statement level")
		}

	default:
		log.Crashf("Unexpected Decl type %T", s.Decl)
	}
	a.compileDecl(s.Decl)
}
示例#7
0
func (b *block) enterChild() *block {
	if b.inner != nil && b.inner.scope == b.scope {
		log.Crash("Failed to exit child block before entering another child")
	}
	sub := &block{
		outer:  b,
		scope:  b.scope,
		defs:   make(map[string]Def),
		offset: b.offset + b.numVars,
	}
	b.inner = sub
	return sub
}
示例#8
0
func (b *block) defineSlot(t Type, temp bool) *Variable {
	if b.inner != nil && b.inner.scope == b.scope {
		log.Crash("Failed to exit child block before defining variable")
	}
	index := -1
	if !b.global || temp {
		index = b.offset + b.numVars
		b.numVars++
		if index >= b.scope.maxVars {
			b.scope.maxVars = index + 1
		}
	}
	v := &Variable{token.Position{}, index, t, nil}
	return v
}
示例#9
0
文件: triv.go 项目: 8l/go-learn
func main() {
	flag.Parse()

	// The counter is published as a variable directly.
	ctr := new(Counter)
	http.Handle("/counter", ctr)
	expvar.Publish("counter", ctr)

	http.Handle("/go/", http.HandlerFunc(FileServer))
	http.Handle("/flags", http.HandlerFunc(FlagServer))
	http.Handle("/args", http.HandlerFunc(ArgServer))
	http.Handle("/go/hello", http.HandlerFunc(HelloServer))
	http.Handle("/chan", ChanCreate())
	http.Handle("/date", http.HandlerFunc(DateServer))
	err := http.ListenAndServe(":12345", nil)
	if err != nil {
		log.Crash("ListenAndServe: ", err)
	}
}
示例#10
0
文件: lilirc.go 项目: strtok/lilirc
func main() {
	// read arguments
	listen_addr := flag.String("listen", "0.0.0.0:6667",
		"Port to listen for IRC connections on")
	log_file := flag.String("log-file", "/dev/stdout", "Where to write log files")
	flag.Parse()

	// Set up logging
	var outFile *os.File
	if *log_file == "/dev/stdout" {
		outFile = os.Stdout
	} else {
		var err os.Error
		outFile, err = os.Open(*log_file, os.O_WRONLY|os.O_CREAT, 0755)
		if err != nil {
			log.Crash("Oh noes!")
		}
	}
	logger = log.New(outFile, nil, "", log.Ldate|log.Ltime)

	listenAddress, err := net.ResolveTCPAddr(*listen_addr)

	if err != nil {
		logger.Log("failed creating listenAddress")
	}

	listener, err := net.ListenTCP("tcp", listenAddress)

	if err != nil {
		logger.Log("failed listening")
	}

	for {

		newConnection, err := listener.AcceptTCP()

		if err != nil {
			logger.Log("failed accepting TCP connection")
		}

		go StartGateway(newConnection)
	}
}
示例#11
0
func (a *stmtCompiler) compileBranchStmt(s *ast.BranchStmt) {
	var pc *uint

	switch s.Tok {
	case token.BREAK:
		l := a.findLexicalLabel(s.Label, func(l *label) bool { return l.breakPC != nil }, "break", "for loop, switch, or select")
		if l == nil {
			return
		}
		pc = l.breakPC

	case token.CONTINUE:
		l := a.findLexicalLabel(s.Label, func(l *label) bool { return l.continuePC != nil }, "continue", "for loop")
		if l == nil {
			return
		}
		pc = l.continuePC

	case token.GOTO:
		l, ok := a.labels[s.Label.Name()]
		if !ok {
			pc := badPC
			l = &label{name: s.Label.Name(), desc: "unresolved label", gotoPC: &pc, used: s.Pos()}
			a.labels[l.name] = l
		}

		pc = l.gotoPC
		a.flow.putGoto(s.Pos(), l.name, a.block)

	case token.FALLTHROUGH:
		a.diag("fallthrough outside switch")
		return

	default:
		log.Crash("Unexpected branch token %v", s.Tok)
	}

	a.flow.put1(false, pc)
	a.push(func(v *Thread) { v.pc = *pc })
}
示例#12
0
func (a *stmtCompiler) compileVarDecl(decl *ast.GenDecl) {
	for _, spec := range decl.Specs {
		spec := spec.(*ast.ValueSpec)
		if spec.Values == nil {
			// Declaration without assignment
			if spec.Type == nil {
				// Parser should have caught
				log.Crash("Type and Values nil")
			}
			t := a.compileType(a.block, spec.Type)
			// Define placeholders even if type compile failed
			for _, n := range spec.Names {
				a.defineVar(n, t)
			}
		} else {
			// Declaration with assignment
			lhs := make([]ast.Expr, len(spec.Names))
			for i, n := range spec.Names {
				lhs[i] = n
			}
			a.doAssign(lhs, spec.Values, decl.Tok, spec.Type)
		}
	}
}
示例#13
0
func (a *stmtCompiler) compile(s ast.Stmt) {
	if a.block.inner != nil {
		log.Crash("Child scope still entered")
	}

	notimpl := false
	switch s := s.(type) {
	case *ast.BadStmt:
		// Error already reported by parser.
		a.silentErrors++

	case *ast.DeclStmt:
		a.compileDeclStmt(s)

	case *ast.EmptyStmt:
		// Do nothing.

	case *ast.LabeledStmt:
		a.compileLabeledStmt(s)

	case *ast.ExprStmt:
		a.compileExprStmt(s)

	case *ast.IncDecStmt:
		a.compileIncDecStmt(s)

	case *ast.AssignStmt:
		a.compileAssignStmt(s)

	case *ast.GoStmt:
		notimpl = true

	case *ast.DeferStmt:
		notimpl = true

	case *ast.ReturnStmt:
		a.compileReturnStmt(s)

	case *ast.BranchStmt:
		a.compileBranchStmt(s)

	case *ast.BlockStmt:
		a.compileBlockStmt(s)

	case *ast.IfStmt:
		a.compileIfStmt(s)

	case *ast.CaseClause:
		a.diag("case clause outside switch")

	case *ast.SwitchStmt:
		a.compileSwitchStmt(s)

	case *ast.TypeCaseClause:
		notimpl = true

	case *ast.TypeSwitchStmt:
		notimpl = true

	case *ast.CommClause:
		notimpl = true

	case *ast.SelectStmt:
		notimpl = true

	case *ast.ForStmt:
		a.compileForStmt(s)

	case *ast.RangeStmt:
		notimpl = true

	default:
		log.Crashf("unexpected ast node type %T", s)
	}

	if notimpl {
		a.diag("%T statment node not implemented", s)
	}

	if a.block.inner != nil {
		log.Crash("Forgot to exit child scope")
	}
}
示例#14
0
func (a *exprInfo) compileSelectorExpr(v *expr, name string) *expr {
	// mark marks a field that matches the selector name.  It
	// tracks the best depth found so far and whether more than
	// one field has been found at that depth.
	bestDepth := -1
	ambig := false
	amberr := ""
	mark := func(depth int, pathName string) {
		switch {
		case bestDepth == -1 || depth < bestDepth:
			bestDepth = depth
			ambig = false
			amberr = ""

		case depth == bestDepth:
			ambig = true

		default:
			log.Crashf("Marked field at depth %d, but already found one at depth %d", depth, bestDepth)
		}
		amberr += "\n\t" + pathName[1:]
	}

	visited := make(map[Type]bool)

	// find recursively searches for the named field, starting at
	// type t.  If it finds the named field, it returns a function
	// which takes an expr that represents a value of type 't' and
	// returns an expr that retrieves the named field.  We delay
	// expr construction to avoid producing lots of useless expr's
	// as we search.
	//
	// TODO(austin) Now that the expression compiler works on
	// semantic values instead of AST's, there should be a much
	// better way of doing this.
	var find func(Type, int, string) func(*expr) *expr
	find = func(t Type, depth int, pathName string) func(*expr) *expr {
		// Don't bother looking if we've found something shallower
		if bestDepth != -1 && bestDepth < depth {
			return nil
		}

		// Don't check the same type twice and avoid loops
		if _, ok := visited[t]; ok {
			return nil
		}
		visited[t] = true

		// Implicit dereference
		deref := false
		if ti, ok := t.(*PtrType); ok {
			deref = true
			t = ti.Elem
		}

		// If it's a named type, look for methods
		if ti, ok := t.(*NamedType); ok {
			_, ok := ti.methods[name]
			if ok {
				mark(depth, pathName+"."+name)
				log.Crash("Methods not implemented")
			}
			t = ti.Def
		}

		// If it's a struct type, check fields and embedded types
		var builder func(*expr) *expr
		if t, ok := t.(*StructType); ok {
			for i, f := range t.Elems {
				var sub func(*expr) *expr
				switch {
				case f.Name == name:
					mark(depth, pathName+"."+name)
					sub = func(e *expr) *expr { return e }

				case f.Anonymous:
					sub = find(f.Type, depth+1, pathName+"."+f.Name)
					if sub == nil {
						continue
					}

				default:
					continue
				}

				// We found something.  Create a
				// builder for accessing this field.
				ft := f.Type
				index := i
				builder = func(parent *expr) *expr {
					if deref {
						parent = a.compileStarExpr(parent)
					}
					expr := a.newExpr(ft, "selector expression")
					pf := parent.asStruct()
					evalAddr := func(t *Thread) Value { return pf(t).Field(t, index) }
					expr.genValue(evalAddr)
					return sub(expr)
				}
			}
		}

		return builder
	}

	builder := find(v.t, 0, "")
	if builder == nil {
		a.diag("type %v has no field or method %s", v.t, name)
		return nil
	}
	if ambig {
		a.diag("field %s is ambiguous in type %v%s", name, v.t, amberr)
		return nil
	}

	return builder(v)
}
示例#15
0
func (a *exprInfo) compileBinaryExpr(op token.Token, l, r *expr) *expr {
	// Save the original types of l.t and r.t for error messages.
	origlt := l.t
	origrt := r.t

	// XXX(Spec) What is the exact definition of a "named type"?

	// XXX(Spec) Arithmetic operators: "Integer types" apparently
	// means all types compatible with basic integer types, though
	// this is never explained.  Likewise for float types, etc.
	// This relates to the missing explanation of named types.

	// XXX(Spec) Operators: "If both operands are ideal numbers,
	// the conversion is to ideal floats if one of the operands is
	// an ideal float (relevant for / and %)."  How is that
	// relevant only for / and %?  If I add an ideal int and an
	// ideal float, I get an ideal float.

	if op != token.SHL && op != token.SHR {
		// Except in shift expressions, if one operand has
		// numeric type and the other operand is an ideal
		// number, the ideal number is converted to match the
		// type of the other operand.
		if (l.t.isInteger() || l.t.isFloat()) && !l.t.isIdeal() && r.t.isIdeal() {
			r = r.convertTo(l.t)
		} else if (r.t.isInteger() || r.t.isFloat()) && !r.t.isIdeal() && l.t.isIdeal() {
			l = l.convertTo(r.t)
		}
		if l == nil || r == nil {
			return nil
		}

		// Except in shift expressions, if both operands are
		// ideal numbers and one is an ideal float, the other
		// is converted to ideal float.
		if l.t.isIdeal() && r.t.isIdeal() {
			if l.t.isInteger() && r.t.isFloat() {
				l = l.convertTo(r.t)
			} else if l.t.isFloat() && r.t.isInteger() {
				r = r.convertTo(l.t)
			}
			if l == nil || r == nil {
				return nil
			}
		}
	}

	// Useful type predicates
	// TODO(austin) CL 33668 mandates identical types except for comparisons.
	compat := func() bool { return l.t.compat(r.t, false) }
	integers := func() bool { return l.t.isInteger() && r.t.isInteger() }
	floats := func() bool { return l.t.isFloat() && r.t.isFloat() }
	strings := func() bool {
		// TODO(austin) Deal with named types
		return l.t == StringType && r.t == StringType
	}
	booleans := func() bool { return l.t.isBoolean() && r.t.isBoolean() }

	// Type check
	var t Type
	switch op {
	case token.ADD:
		if !compat() || (!integers() && !floats() && !strings()) {
			a.diagOpTypes(op, origlt, origrt)
			return nil
		}
		t = l.t

	case token.SUB, token.MUL, token.QUO:
		if !compat() || (!integers() && !floats()) {
			a.diagOpTypes(op, origlt, origrt)
			return nil
		}
		t = l.t

	case token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
		if !compat() || !integers() {
			a.diagOpTypes(op, origlt, origrt)
			return nil
		}
		t = l.t

	case token.SHL, token.SHR:
		// XXX(Spec) Is it okay for the right operand to be an
		// ideal float with no fractional part?  "The right
		// operand in a shift operation must be always be of
		// unsigned integer type or an ideal number that can
		// be safely converted into an unsigned integer type
		// (§Arithmetic operators)" suggests so and 6g agrees.

		if !l.t.isInteger() || !(r.t.isInteger() || r.t.isIdeal()) {
			a.diagOpTypes(op, origlt, origrt)
			return nil
		}

		// The right operand in a shift operation must be
		// always be of unsigned integer type or an ideal
		// number that can be safely converted into an
		// unsigned integer type.
		if r.t.isIdeal() {
			r2 := r.convertTo(UintType)
			if r2 == nil {
				return nil
			}

			// If the left operand is not ideal, convert
			// the right to not ideal.
			if !l.t.isIdeal() {
				r = r2
			}

			// If both are ideal, but the right side isn't
			// an ideal int, convert it to simplify things.
			if l.t.isIdeal() && !r.t.isInteger() {
				r = r.convertTo(IdealIntType)
				if r == nil {
					log.Crashf("conversion to uintType succeeded, but conversion to idealIntType failed")
				}
			}
		} else if _, ok := r.t.lit().(*uintType); !ok {
			a.diag("right operand of shift must be unsigned")
			return nil
		}

		if l.t.isIdeal() && !r.t.isIdeal() {
			// XXX(Spec) What is the meaning of "ideal >>
			// non-ideal"?  Russ says the ideal should be
			// converted to an int.  6g propagates the
			// type down from assignments as a hint.

			l = l.convertTo(IntType)
			if l == nil {
				return nil
			}
		}

		// At this point, we should have one of three cases:
		// 1) uint SHIFT uint
		// 2) int SHIFT uint
		// 3) ideal int SHIFT ideal int

		t = l.t

	case token.LOR, token.LAND:
		if !booleans() {
			return nil
		}
		// XXX(Spec) There's no mention of *which* boolean
		// type the logical operators return.  From poking at
		// 6g, it appears to be the named boolean type, NOT
		// the type of the left operand, and NOT an unnamed
		// boolean type.

		t = BoolType

	case token.ARROW:
		// The operands in channel sends differ in type: one
		// is always a channel and the other is a variable or
		// value of the channel's element type.
		log.Crash("Binary op <- not implemented")
		t = BoolType

	case token.LSS, token.GTR, token.LEQ, token.GEQ:
		// XXX(Spec) It's really unclear what types which
		// comparison operators apply to.  I feel like the
		// text is trying to paint a Venn diagram for me,
		// which it's really pretty simple: <, <=, >, >= apply
		// only to numeric types and strings.  == and != apply
		// to everything except arrays and structs, and there
		// are some restrictions on when it applies to slices.

		if !compat() || (!integers() && !floats() && !strings()) {
			a.diagOpTypes(op, origlt, origrt)
			return nil
		}
		t = BoolType

	case token.EQL, token.NEQ:
		// XXX(Spec) The rules for type checking comparison
		// operators are spread across three places that all
		// partially overlap with each other: the Comparison
		// Compatibility section, the Operators section, and
		// the Comparison Operators section.  The Operators
		// section should just say that operators require
		// identical types (as it does currently) except that
		// there a few special cases for comparison, which are
		// described in section X.  Currently it includes just
		// one of the four special cases.  The Comparison
		// Compatibility section and the Comparison Operators
		// section should either be merged, or at least the
		// Comparison Compatibility section should be
		// exclusively about type checking and the Comparison
		// Operators section should be exclusively about
		// semantics.

		// XXX(Spec) Comparison operators: "All comparison
		// operators apply to basic types except bools."  This
		// is very difficult to parse.  It's explained much
		// better in the Comparison Compatibility section.

		// XXX(Spec) Comparison compatibility: "Function
		// values are equal if they refer to the same
		// function." is rather vague.  It should probably be
		// similar to the way the rule for map values is
		// written: Function values are equal if they were
		// created by the same execution of a function literal
		// or refer to the same function declaration.  This is
		// *almost* but not quite waht 6g implements.  If a
		// function literals does not capture any variables,
		// then multiple executions of it will result in the
		// same closure.  Russ says he'll change that.

		// TODO(austin) Deal with remaining special cases

		if !compat() {
			a.diagOpTypes(op, origlt, origrt)
			return nil
		}
		// Arrays and structs may not be compared to anything.
		switch l.t.(type) {
		case *ArrayType, *StructType:
			a.diagOpTypes(op, origlt, origrt)
			return nil
		}
		t = BoolType

	default:
		log.Crashf("unknown binary operator %v", op)
	}

	desc, ok := binOpDescs[op]
	if !ok {
		desc = op.String() + " expression"
		binOpDescs[op] = desc
	}

	// Check for ideal divide by zero
	switch op {
	case token.QUO, token.REM:
		if r.t.isIdeal() {
			if (r.t.isInteger() && r.asIdealInt()().IsZero()) ||
				(r.t.isFloat() && r.asIdealFloat()().IsZero()) {
				a.diag("divide by zero")
				return nil
			}
		}
	}

	// Compile
	expr := a.newExpr(t, desc)
	switch op {
	case token.ADD:
		expr.genBinOpAdd(l, r)

	case token.SUB:
		expr.genBinOpSub(l, r)

	case token.MUL:
		expr.genBinOpMul(l, r)

	case token.QUO:
		expr.genBinOpQuo(l, r)

	case token.REM:
		expr.genBinOpRem(l, r)

	case token.AND:
		expr.genBinOpAnd(l, r)

	case token.OR:
		expr.genBinOpOr(l, r)

	case token.XOR:
		expr.genBinOpXor(l, r)

	case token.AND_NOT:
		expr.genBinOpAndNot(l, r)

	case token.SHL:
		if l.t.isIdeal() {
			lv := l.asIdealInt()()
			rv := r.asIdealInt()()
			const maxShift = 99999
			if rv.Cmp(bignum.Int(maxShift)) > 0 {
				a.diag("left shift by %v; exceeds implementation limit of %v", rv, maxShift)
				expr.t = nil
				return nil
			}
			val := lv.Shl(uint(rv.Value()))
			expr.eval = func() *bignum.Integer { return val }
		} else {
			expr.genBinOpShl(l, r)
		}

	case token.SHR:
		if l.t.isIdeal() {
			lv := l.asIdealInt()()
			rv := r.asIdealInt()()
			val := lv.Shr(uint(rv.Value()))
			expr.eval = func() *bignum.Integer { return val }
		} else {
			expr.genBinOpShr(l, r)
		}

	case token.LSS:
		expr.genBinOpLss(l, r)

	case token.GTR:
		expr.genBinOpGtr(l, r)

	case token.LEQ:
		expr.genBinOpLeq(l, r)

	case token.GEQ:
		expr.genBinOpGeq(l, r)

	case token.EQL:
		expr.genBinOpEql(l, r)

	case token.NEQ:
		expr.genBinOpNeq(l, r)

	case token.LAND:
		expr.genBinOpLogAnd(l, r)

	case token.LOR:
		expr.genBinOpLogOr(l, r)

	default:
		log.Crashf("Compilation of binary op %v not implemented", op)
	}

	return expr
}