package eval
import (
)
type compiler struct {
builtin *staticNs
scopes []*staticNs
captures []*staticUpNs
warn io.Writer
deprecations deprecationRegistry
srcMeta parse.Source
}
type capture struct {
name string
local bool
index int
}
func (, *staticNs, parse.Tree, io.Writer) ( nsOp, error) {
= .clone()
:= &compiler{
, []*staticNs{}, []*staticUpNs{new(staticUpNs)},
, newDeprecationRegistry(), .Source}
defer func() {
:= recover()
if == nil {
return
} else if := GetCompilationError(); != nil {
=
} else {
panic()
}
}()
:= .chunkOp(.Root)
return nsOp{, }, nil
}
type nsOp struct {
inner effectOp
template *staticNs
}
func ( nsOp) ( *Frame) (*Ns, func() Exception) {
if len(.template.names) > len(.local.names) {
:= len(.template.names)
:= &Ns{make([]vars.Var, ), .template.names, .template.deleted}
copy(.slots, .local.slots)
for := len(.local.names); < ; ++ {
.slots[] = MakeVarFromName(.names[])
}
.local =
} else {
.local = &Ns{.local.slots, .local.names, .template.deleted}
}
return .local, func() Exception { return .inner.exec() }
}
const compilationErrorType = "compilation error"
func ( *compiler) ( diag.Ranger, string, ...interface{}) {
panic(&diag.Error{
Type: compilationErrorType,
Message: fmt.Sprintf(, ...),
Context: *diag.NewContext(.srcMeta.Name, .srcMeta.Code, )})
}
func ( interface{}) *diag.Error {
if , := .(*diag.Error); && .Type == compilationErrorType {
return
}
return nil
}
func ( *compiler) () *staticNs {
return .scopes[len(.scopes)-1]
}
func ( *compiler) () (*staticNs, *staticUpNs) {
:= new(staticNs)
:= new(staticUpNs)
.scopes = append(.scopes, )
.captures = append(.captures, )
return ,
}
func ( *compiler) () {
.scopes[len(.scopes)-1] = nil
.scopes = .scopes[:len(.scopes)-1]
.captures[len(.captures)-1] = nil
.captures = .captures[:len(.captures)-1]
}
func ( *compiler) ( string, diag.Ranger) {
:= ""
:= 16
switch {
case "fopen~":
= `the "fopen" command is deprecated; use "file:open" instead`
case "fclose~":
= `the "fclose" command is deprecated; use "file:close" instead`
case "pipe~":
= `the "pipe" command is deprecated; use "file:pipe" instead`
case "prclose~":
= `the "prclose" command is deprecated; use "file:prclose" instead`
case "pwclose":
= `the "pwclose" command is deprecated; use "file:pwclose" instead`
default:
return
}
.deprecate(, , )
}
func ( *compiler) ( diag.Ranger, string, int) {
if .warn == nil || == nil {
return
}
:= deprecation{.srcMeta.Name, .Range(), }
if prog.DeprecationLevel >= && .deprecations.register() {
:= diag.Error{
Type: "deprecation", Message: ,
Context: diag.Context{
Name: .srcMeta.Name, Source: .srcMeta.Code, Ranging: .Range()}}
fmt.Fprintln(.warn, .Show(""))
}
}