Skip to content
Permalink
Browse files

Started refactoring to simplify context handling.

  • Loading branch information...
renato
renato committed Mar 3, 2019
1 parent e558e06 commit 49812221fa88498ae0ffc2a092235950ffd38fab
Showing with 85 additions and 157 deletions.
  1. +5 −7 mg/expression.go
  2. +3 −7 mg/include.go
  3. +26 −0 mg/map_context.go
  4. +19 −52 mg/process.go
  5. +22 −0 mg/string.go
  6. +10 −91 mg/types.go
@@ -13,27 +13,25 @@ type DefineContent struct {
Name string
Expr *expression.Expression
Location Location
scope Scope
latestInclusions []InclusionChainItem
}

type ExpressionContent struct {
Expr *expression.Expression
Text string
Location Location
scope Scope
}

func NewExpression(arg string, location Location, original string, scope Scope) Content {
func NewExpression(arg string, location Location, original string) Content {
expr, err := expression.ParseExpr(arg)
if err != nil {
log.Printf("WARNING: (%s) Unable to eval: %s (%s)", location.String(), arg, err.Error())
return unevaluatedExpression(original)
}
return &ExpressionContent{Expr: &expr, Location: location, Text: original, scope: scope}
return &ExpressionContent{Expr: &expr, Location: location, Text: original}
}

func NewVariable(arg string, location Location, original string, scope Scope) Content {
func NewVariable(arg string, location Location, original string) Content {
parts := strings.SplitN(strings.TrimSpace(arg), " ", 2)
if len(parts) == 2 {
variable, rawExpr := parts[0], parts[1]
@@ -43,7 +41,7 @@ func NewVariable(arg string, location Location, original string, scope Scope) Co
location.String(), variable, rawExpr, err.Error())
return unevaluatedExpression(original)
}
return &DefineContent{Name: variable, Expr: &expr, Location: location, scope: scope}
return &DefineContent{Name: variable, Expr: &expr, Location: location}
}
log.Printf("WARNING: (%s) malformed define expression: %s", location.String(), arg)
return unevaluatedExpression(original)
@@ -55,6 +53,7 @@ func unevaluatedExpression(original string) Content {

var _ Content = (*ExpressionContent)(nil)

// FIXME
func (e *ExpressionContent) Write(writer io.Writer, files WebFilesMap, inclusionChain []InclusionChainItem) error {
r, err := expression.EvalExpr(*e.Expr, magParams{
webFiles: &files,
@@ -78,7 +77,6 @@ func (e *ExpressionContent) String() string {
}

var _ Content = (*DefineContent)(nil)
var _ SideEffectContent = (*DefineContent)(nil)

func (d *DefineContent) Write(writer io.Writer, files WebFilesMap, inclusionChain []InclusionChainItem) error {
d.Run(&files, inclusionChain)
@@ -10,12 +10,11 @@ type IncludeInstruction struct {
Text string
Path string
Origin Location
scope Scope
Resolver FileResolver
}

func NewIncludeInstruction(arg string, location Location, original string, scope Scope, resolver FileResolver) *IncludeInstruction {
return &IncludeInstruction{Text: original, Path: arg, Origin: location, scope: scope, Resolver: resolver}
func NewIncludeInstruction(arg string, location Location, original string, resolver FileResolver) *IncludeInstruction {
return &IncludeInstruction{Text: original, Path: arg, Origin: location, Resolver: resolver}
}

func (inc *IncludeInstruction) String() string {
@@ -33,7 +32,7 @@ func (inc *IncludeInstruction) Write(writer io.Writer, files WebFilesMap, inclus
return &MagnanimousError{Code: IOError, message: err.Error()}
}
} else {
inclusionChain = append(inclusionChain, InclusionChainItem{Location: &inc.Origin, scope: inc.scope})
inclusionChain = append(inclusionChain, InclusionChainItem{Location: &inc.Origin})
//ss:= inclusionChainToString(inclusionChain)
//fmt.Printf("Chain: %s", ss)
for _, f := range inclusionChain {
@@ -51,9 +50,6 @@ func (inc *IncludeInstruction) Write(writer io.Writer, files WebFilesMap, inclus
if err != nil {
return err
}

// mix in the context of the include file into the surrounding context
webFile.Processed.Context().mixInto(inc.scope.Context())
}
return nil
}
@@ -0,0 +1,26 @@
package mg

type MapContext struct {
Map map[string]interface{}
}

var _ Context = (*MapContext)(nil)

func (m *MapContext) Get(name string) (interface{}, bool) {
v, ok := m.Map[name]
return v, ok
}

func (m *MapContext) Set(name string, value interface{}) {
m.Map[name] = value
}

func (m *MapContext) IsEmpty() bool {
return len(m.Map) == 0
}

func (m *MapContext) mixInto(other Context) {
for k, v := range m.Map {
other.Set(k, v)
}
}
@@ -2,7 +2,6 @@ package mg

import (
"bufio"
"fmt"
"io"
"log"
"os"
@@ -38,11 +37,6 @@ func ProcessAll(files []string, basePath, sourcesDir string, webFiles *WebFilesM
}
webFiles.WebFiles[file] = *wf
}
if globalCtx, ok := webFiles.WebFiles[filepath.Join(basePath, "_global_context")]; ok {
globalCtx.runSideEffects(webFiles, nil)
var globalContext RootScope = globalCtx.Processed.Context()
webFiles.GlobalContext = globalContext
}
return nil
}

@@ -60,7 +54,6 @@ func ProcessFile(file, basePath string, resolver FileResolver) (*WebFile, error)
if magErr != nil {
return nil, magErr
}
processed.scopeStack = nil // the stack is no longer required
nonWritable := strings.HasPrefix(filepath.Base(file), "_")
return &WebFile{BasePath: basePath, Name: filepath.Base(file), Processed: processed, NonWritable: nonWritable}, nil
}
@@ -69,7 +62,7 @@ func ProcessReader(reader *bufio.Reader, file string, sizeHint int, resolver Fil
var builder strings.Builder
builder.Grow(sizeHint)
isMarkDown := isMd(file)
processed := ProcessedFile{context: make(map[string]interface{}, 4)}
processed := ProcessedFile{}
state := parserState{file: file, row: 1, col: 1, builder: &builder, reader: reader, pf: &processed}
magErr := parseText(&state, resolver)
if magErr != nil {
@@ -98,37 +91,45 @@ func appendInstructionContent(pf *ProcessedFile, text string, location Location,
pf.AppendContent(unevaluatedExpression(text))
}
case 2:
content := createInstruction(parts[0], parts[1], pf.currentScope(), location, text, resolver)
content := createInstruction(parts[0], parts[1], location, text, resolver)
if content != nil {
pf.AppendContent(content)
}
}
}

func createInstruction(name, arg string, scope Scope, location Location,
func createInstruction(name, arg string, location Location,
original string, resolver FileResolver) Content {
switch strings.TrimSpace(name) {
case "include":
return NewIncludeInstruction(arg, location, original, scope, resolver)
return NewIncludeInstruction(arg, location, original, resolver)
case "define":
return NewVariable(arg, location, original, scope)
return NewVariable(arg, location, original)
case "eval":
return NewExpression(arg, location, original, scope)
return NewExpression(arg, location, original)
case "if":
return NewIfInstruction(arg, location, original, scope)
return NewIfInstruction(arg, location, original)
case "for":
return NewForInstruction(arg, location, original, scope, resolver)
return NewForInstruction(arg, location, original, resolver)
case "doc":
return nil
case "component":
return NewComponentInstruction(arg, location, original, scope, resolver)
return NewComponentInstruction(arg, location, original, resolver)
}

log.Printf("WARNING: (%s) Unknown instruction: '%s'", location.String(), name)
return unevaluatedExpression(original)
}

func WriteTo(dir string, filesMap WebFilesMap) error {
// FIXME evaluate global context first
if globalCtx, ok := filesMap.WebFiles[filepath.Join(basePath, "_global_context")]; ok {
//globalCtx.runSideEffects(webFiles, nil)
globalCtx.Write()
var globalContext RootContext = globalCtx.()
webFiles.GlobalContext = globalContext
}

err := os.MkdirAll(dir, 0770)
if err != nil {
return &MagnanimousError{Code: IOError, message: err.Error()}
@@ -177,38 +178,13 @@ func writeFile(file, targetFile string, wf WebFile, filesMap WebFilesMap) error
return nil
}

func (c *StringContent) Write(writer io.Writer, files WebFilesMap, inclusionChain []InclusionChainItem) error {
_, err := writer.Write([]byte(c.Text))
if err != nil {
return &MagnanimousError{Code: IOError, message: err.Error()}
}
return nil
}

func (c *StringContent) String() string {
return fmt.Sprintf("StringContent{%s}", c.Text)
}

func (wf *WebFile) Write(writer io.Writer, files WebFilesMap, inclusionChain []InclusionChainItem) error {
return writeContents(wf.Processed, writer, files, inclusionChain, false)
}

func (wf *WebFile) runSideEffects(files *WebFilesMap, inclusionChain []InclusionChainItem) {
runSideEffects(wf.Processed, files, inclusionChain)
return writeContents(wf.Processed, writer, files, inclusionChain)
}

func writeContents(cc ContentContainer, writer io.Writer, files WebFilesMap,
inclusionChain []InclusionChainItem, runSideEffectsFirst bool) error {
if runSideEffectsFirst {
runSideEffects(cc, &files, inclusionChain)
}
inclusionChain []InclusionChainItem) error {
for _, c := range cc.GetContents() {
if runSideEffectsFirst {
// only skip define content because not all SideEffectContent does only side-effect
if _, skip := c.(*DefineContent); skip {
continue
}
}
err := c.Write(writer, files, inclusionChain)
if err != nil {
return err
@@ -217,15 +193,6 @@ func writeContents(cc ContentContainer, writer io.Writer, files WebFilesMap,
return nil
}

func runSideEffects(container ContentContainer, files *WebFilesMap, inclusionChain []InclusionChainItem) {
for _, c := range container.GetContents() {
switch sf := c.(type) {
case SideEffectContent:
sf.Run(files, inclusionChain)
}
}
}

func inclusionChainToString(locations []InclusionChainItem) string {
var b strings.Builder
b.WriteRune('[')
@@ -0,0 +1,22 @@
package mg

import (
"fmt"
"io"
)

type StringContent struct {
Text string
}

func (c *StringContent) Write(writer io.Writer, files WebFilesMap, inclusionChain []InclusionChainItem) error {
_, err := writer.Write([]byte(c.Text))
if err != nil {
return &MagnanimousError{Code: IOError, message: err.Error()}
}
return nil
}

func (c *StringContent) String() string {
return fmt.Sprintf("StringContent{%s}", c.Text)
}

0 comments on commit 4981222

Please sign in to comment.
You can’t perform that action at this time.