Exemplo n.º 1
0
func (c *funcContext) translateLoopingStmt(cond func() string, body *ast.BlockStmt, bodyPrefix, post func(), label *types.Label, flatten bool) {
	prevFlowData := c.flowDatas[nil]
	data := &flowData{
		postStmt: post,
	}
	if flatten {
		data.beginCase = c.caseCounter
		data.endCase = c.caseCounter + 1
		c.caseCounter += 2
	}
	c.flowDatas[nil] = data
	c.flowDatas[label] = data
	defer func() {
		delete(c.flowDatas, label)
		c.flowDatas[nil] = prevFlowData
	}()

	if !flatten && label != nil {
		c.Printf("%s:", label.Name())
	}
	c.PrintCond(!flatten, "while (true) {", fmt.Sprintf("case %d:", data.beginCase))
	c.Indent(func() {
		condStr := cond()
		if condStr != "true" {
			c.PrintCond(!flatten, fmt.Sprintf("if (!(%s)) { break; }", condStr), fmt.Sprintf("if(!(%s)) { $s = %d; continue; }", condStr, data.endCase))
		}

		prevEV := c.p.escapingVars
		c.handleEscapingVars(body)

		if bodyPrefix != nil {
			bodyPrefix()
		}
		c.translateStmtList(body.List)
		isTerminated := false
		if len(body.List) != 0 {
			switch body.List[len(body.List)-1].(type) {
			case *ast.ReturnStmt, *ast.BranchStmt:
				isTerminated = true
			}
		}
		if !isTerminated {
			post()
		}

		c.p.escapingVars = prevEV
	})
	c.PrintCond(!flatten, "}", fmt.Sprintf("$s = %d; continue; case %d:", data.beginCase, data.endCase))
}
Exemplo n.º 2
0
func (r *renamer) checkLabel(label *types.Label) {
	// Check there are no identical labels in the function's label block.
	// (Label blocks don't nest, so this is easy.)
	if prev := label.Parent().Lookup(r.to); prev != nil {
		r.errorf(label.Pos(), "renaming this label %q to %q", label.Name(), prev.Name())
		r.errorf(prev.Pos(), "\twould conflict with this one")
	}
}
Exemplo n.º 3
0
func (c *funcContext) translateBranchingStmt(caseClauses []ast.Stmt, isSwitch bool, translateCond func(ast.Expr) *expression, printCaseBodyPrefix func(int), label *types.Label, flatten bool) {
	var branches []*branch
	var defaultBranch *branch
	var openBranches []*branch
clauseLoop:
	for i, cc := range caseClauses {
		clause := cc.(*ast.CaseClause)

		branch := &branch{index: i, clause: clause}
		openBranches = append(openBranches, branch)
		for _, openBranch := range openBranches {
			openBranch.body = append(openBranch.body, clause.Body...)
		}
		if !hasFallthrough(clause) {
			openBranches = nil
		}

		if len(clause.List) == 0 {
			defaultBranch = branch
			continue
		}

		for _, cond := range clause.List {
			if translateCond == nil {
				if b, ok := analysis.BoolValue(cond, c.p.Info.Info); ok {
					if b {
						defaultBranch = branch
						break clauseLoop
					}
					continue
				}
			}
			branch.conds = append(branch.conds, cond)
		}
		if len(branch.conds) == 0 {
			continue
		}

		branches = append(branches, branch)
	}

	for defaultBranch == nil && len(branches) != 0 && len(branches[len(branches)-1].body) == 0 {
		branches = branches[:len(branches)-1]
	}

	if len(branches) == 0 {
		if defaultBranch != nil {
			c.translateStmtList(defaultBranch.body)
			return
		}
		return
	}

	hasBreak := false
	if isSwitch {
		switch label {
		case nil:
			for _, child := range caseClauses {
				if analysis.HasBreak(child) {
					hasBreak = true
					break
				}
			}
		default:
			hasBreak = true // always assume break if label is given
		}
	}

	var caseOffset, endCase int
	if flatten {
		caseOffset = c.caseCounter
		endCase = caseOffset + len(branches)
		if defaultBranch != nil {
			endCase++
		}
		c.caseCounter = endCase + 1
	}

	if isSwitch {
		prevFlowData := c.flowDatas[nil]
		data := &flowData{
			postStmt:  prevFlowData.postStmt,  // for "continue" of outer loop
			beginCase: prevFlowData.beginCase, // same
			endCase:   endCase,
		}
		c.flowDatas[nil] = data
		c.flowDatas[label] = data
		defer func() {
			delete(c.flowDatas, label)
			c.flowDatas[nil] = prevFlowData
		}()
	}

	if isSwitch && !flatten && label != nil {
		c.Printf("%s:", label.Name())
	}
	prefix := ""
	if hasBreak {
		prefix = "switch (0) { default: "
	}
	for i, b := range branches {
		conds := make([]string, len(b.conds))
		for i, cond := range b.conds {
			if translateCond == nil {
				conds[i] = c.translateExpr(cond).String()
				continue
			}
			conds[i] = translateCond(cond).String()
		}
		b.condStr = strings.Join(conds, " || ")
		if flatten {
			c.Printf("/* */ if (%s) { $s = %d; continue; }", b.condStr, caseOffset+i)
		}
	}
	if flatten {
		c.Printf("/* */ $s = %d; continue;", caseOffset+len(branches))
	}
	for i, b := range branches {
		c.SetPos(b.clause.Pos())
		c.PrintCond(!flatten, fmt.Sprintf("%sif (%s) {", prefix, b.condStr), fmt.Sprintf("case %d:", caseOffset+i))
		c.Indent(func() {
			if printCaseBodyPrefix != nil {
				printCaseBodyPrefix(b.index)
			}
			c.translateStmtList(b.body)
			if flatten && (defaultBranch != nil || i != len(branches)-1) {
				c.Printf("$s = %d; continue;", endCase)
			}
		})
		prefix = "} else "
	}
	if defaultBranch != nil {
		c.PrintCond(!flatten, "} else {", fmt.Sprintf("case %d:", caseOffset+len(branches)))
		c.Indent(func() {
			if printCaseBodyPrefix != nil {
				printCaseBodyPrefix(defaultBranch.index)
			}
			c.translateStmtList(defaultBranch.body)
		})
	}
	if hasBreak {
		c.PrintCond(!flatten, "} }", fmt.Sprintf("case %d:", endCase))
		return
	}
	c.PrintCond(!flatten, "}", fmt.Sprintf("case %d:", endCase))
}