代码拉取完成,页面将自动刷新
// Copyright 2018 The go-python Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Code objects
package py
import (
"strings"
)
// Code object
//
// Freevars are variables declared in the namespace where the
// code object was defined, they are used when closures are
// used - these become Cellvars in the function with a closure.
//
// Cellvars are names of local variables referenced by functions with
// a closure.
type Code struct {
Argcount int32 // #arguments, except *args
Kwonlyargcount int32 // #keyword only arguments
Nlocals int32 // #local variables
Stacksize int32 // #entries needed for evaluation stack
Flags int32 // CO_..., see below
Code string // instruction opcodes
Consts Tuple // list (constants used)
Names []string // list of strings (names used)
Varnames []string // tuple of strings (local variable names)
Freevars []string // tuple of strings (free variable names)
Cellvars []string // tuple of strings (cell variable names)
// The rest doesn't count for hash or comparisons
Cell2arg []byte // Maps cell vars which are arguments.
Filename string // unicode (where it was loaded from)
Name string // unicode (name, for reference)
Firstlineno int32 // first source line number
Lnotab string // string (encoding addr<->lineno mapping) See Objects/lnotab_notes.txt for details.
Weakreflist *List // to support weakrefs to code objects
}
var CodeType = NewType("code", "code(argcount, kwonlyargcount, nlocals, stacksize, flags, codestring,\n constants, names, varnames, filename, name, firstlineno,\n lnotab[, freevars[, cellvars]])\n\nCreate a code object. Not for the faint of heart.")
// Type of this object
func (o *Code) Type() *Type {
return CodeType
}
// Make sure it satisfies the interface
var _ Object = (*Code)(nil)
const (
// Masks for flags above
CO_OPTIMIZED = 0x0001
CO_NEWLOCALS = 0x0002
CO_VARARGS = 0x0004
CO_VARKEYWORDS = 0x0008
CO_NESTED = 0x0010
CO_GENERATOR = 0x0020
// The CO_NOFREE flag is set if there are no free or cell
// variables. This information is redundant, but it allows a
// single flag test to determine whether there is any extra
// work to be done when the call frame it setup.
CO_NOFREE = 0x0040
CO_GENERATOR_ALLOWED = 0x1000
CO_FUTURE_DIVISION = 0x2000
CO_FUTURE_ABSOLUTE_IMPORT = 0x4000 // do absolute imports by default
CO_FUTURE_WITH_STATEMENT = 0x8000
CO_FUTURE_PRINT_FUNCTION = 0x10000
CO_FUTURE_UNICODE_LITERALS = 0x20000
CO_FUTURE_BARRY_AS_BDFL = 0x40000
CO_COMPILER_FLAGS_MASK = CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL
// This value is found in the cell2arg array when the
// associated cell variable does not correspond to an
// argument. The maximum number of arguments is 255 (indexed
// up to 254), so 255 work as a special flag.
CO_CELL_NOT_AN_ARG = 255
CO_MAXBLOCKS = 20 // Max static block nesting within a function
)
// Intern all the strings in the tuple
func intern_strings(tuple Tuple) {
for i, v_ := range tuple {
v := v_.(String)
tuple[i] = v.Intern()
}
}
const NAME_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
// all_name_chars(s): true iff all chars in s are valid NAME_CHARS
func all_name_chars(s String) bool {
for _, c := range s {
if strings.IndexRune(NAME_CHARS, c) < 0 {
return false
}
}
return true
}
// Make a new code object
func NewCode(argcount int32, kwonlyargcount int32,
nlocals int32, stacksize int32, flags int32,
code_ Object, consts_ Object, names_ Object,
varnames_ Object, freevars_ Object, cellvars_ Object,
filename_ Object, name_ Object, firstlineno int32,
lnotab_ Object) *Code {
var cell2arg []byte
// Type assert the objects
consts := consts_.(Tuple)
namesTuple := names_.(Tuple)
varnamesTuple := varnames_.(Tuple)
freevarsTuple := freevars_.(Tuple)
cellvarsTuple := cellvars_.(Tuple)
name := string(name_.(String))
filename := string(filename_.(String))
lnotab := string(lnotab_.(String))
code := string(code_.(String))
// Convert Tuples to native []string for speed
names := make([]string, len(namesTuple))
for i := range namesTuple {
names[i] = string(namesTuple[i].(String))
}
varnames := make([]string, len(varnamesTuple))
for i := range varnamesTuple {
varnames[i] = string(varnamesTuple[i].(String))
}
freevars := make([]string, len(freevarsTuple))
for i := range freevarsTuple {
freevars[i] = string(freevarsTuple[i].(String))
}
cellvars := make([]string, len(cellvarsTuple))
for i := range cellvarsTuple {
cellvars[i] = string(cellvarsTuple[i].(String))
}
// Check argument types
if argcount < 0 || kwonlyargcount < 0 || nlocals < 0 {
panic("Bad arguments to NewCode")
}
// Ensure that the filename is a ready Unicode string
// FIXME
// if PyUnicode_READY(filename) < 0 {
// return nil;
// }
n_cellvars := len(cellvars)
intern_strings(namesTuple)
intern_strings(varnamesTuple)
intern_strings(freevarsTuple)
intern_strings(cellvarsTuple)
/* Intern selected string constants */
for i := len(consts) - 1; i >= 0; i-- {
if v, ok := consts[i].(String); ok {
if all_name_chars(v) {
consts[i] = v.Intern()
}
}
}
/* Create mapping between cells and arguments if needed. */
if n_cellvars != 0 {
total_args := argcount + kwonlyargcount
if flags&CO_VARARGS != 0 {
total_args++
}
if flags&CO_VARKEYWORDS != 0 {
total_args++
}
used_cell2arg := false
cell2arg = make([]byte, n_cellvars)
for i := range cell2arg {
cell2arg[i] = CO_CELL_NOT_AN_ARG
}
// Find cells which are also arguments.
for i, cell := range cellvars {
for j := int32(0); j < total_args; j++ {
arg := varnames[j]
if cell == arg {
cell2arg[i] = byte(j)
used_cell2arg = true
break
}
}
}
if !used_cell2arg {
cell2arg = nil
}
}
return &Code{
Argcount: argcount,
Kwonlyargcount: kwonlyargcount,
Nlocals: nlocals,
Stacksize: stacksize,
Flags: flags,
Code: code,
Consts: consts,
Names: names,
Varnames: varnames,
Freevars: freevars,
Cellvars: cellvars,
Cell2arg: cell2arg,
Filename: filename,
Name: name,
Firstlineno: firstlineno,
Lnotab: lnotab,
Weakreflist: nil,
}
}
// Return number of free variables
func (co *Code) GetNumFree() int {
return len(co.Freevars)
}
// Use co_lnotab to compute the line number from a bytecode index,
// addrq. See lnotab_notes.txt for the details of the lnotab
// representation.
func (co *Code) Addr2Line(addrq int32) int32 {
line := co.Firstlineno
addr := int32(0)
for i := 0; i < len(co.Lnotab); i += 2 {
addr += int32(co.Lnotab[i])
if addr > addrq {
break
}
line += int32(co.Lnotab[i+1])
}
return line
}
// FIXME this should be the default?
func (co *Code) M__eq__(other Object) (Object, error) {
if otherCo, ok := other.(*Code); ok && co == otherCo {
return True, nil
}
return False, nil
}
// FIXME this should be the default?
func (co *Code) M__ne__(other Object) (Object, error) {
if otherCo, ok := other.(*Code); ok && co == otherCo {
return False, nil
}
return True, nil
}
// Check interface is satisfied
var _ I__eq__ = (*Code)(nil)
var _ I__ne__ = (*Code)(nil)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。