Skip to content

Commit

Permalink
Take context state into account for string serialization.
Browse files Browse the repository at this point in the history
  • Loading branch information
corywalker committed Jul 21, 2017
1 parent bc727df commit a43cf34
Show file tree
Hide file tree
Showing 22 changed files with 112 additions and 84 deletions.
5 changes: 3 additions & 2 deletions example/calc.go
Expand Up @@ -65,6 +65,7 @@ func main() {

if !isNull {
// Print formatted result
context, contextPath := expreduce.ActualStringFormArgs(es)
specialForms := []string{
"System`FullForm",
"System`OutputForm",
Expand All @@ -82,12 +83,12 @@ func main() {
"Out[%d]//%s= %s\n\n",
promptNum,
specialForm,
asSpecialForm.Parts[1].StringForm(specialForm),
asSpecialForm.Parts[1].StringForm(specialForm, context, contextPath),
)
wasSpecialForm = true
}
if !wasSpecialForm {
fmt.Printf("Out[%d]= %s\n\n", promptNum, res.StringForm("System`InputForm"))
fmt.Printf("Out[%d]= %s\n\n", promptNum, res.StringForm("System`InputForm", context, contextPath))
}
}

Expand Down
8 changes: 4 additions & 4 deletions expreduce/builtin_arithmetic.go
Expand Up @@ -229,8 +229,8 @@ func getArithmeticDefinitions() (defs []Definition) {
// The world is not ready for this madness.
//{"Verbatim[Plus][beg___, Verbatim[Times][Optional[c1_?NumberQ],a__], Verbatim[Times][Optional[c2_?NumberQ],a__], end___]", "beg+(c1+c2)*a+end"},
},
toString: func(this *Expression, form string) (bool, string) {
return ToStringInfix(this.Parts[1:], " + ", form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringInfix(this.Parts[1:], " + ", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
// Calls without argument receive identity values
Expand Down Expand Up @@ -387,8 +387,8 @@ func getArithmeticDefinitions() (defs []Definition) {
{"(1/Infinity)", "0"},
{"Times[ComplexInfinity, rest___]", "ComplexInfinity"},
},
toString: func(this *Expression, form string) (bool, string) {
return ToStringInfix(this.Parts[1:], " * ", form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringInfix(this.Parts[1:], " * ", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
// Calls without argument receive identity values
Expand Down
8 changes: 4 additions & 4 deletions expreduce/builtin_boolean.go
Expand Up @@ -5,8 +5,8 @@ func GetBooleanDefinitions() (defs []Definition) {
Name: "And",
Usage: "`e1 && e2 && ...` returns `True` if all expressions evaluate to `True`.",
Attributes: []string{"Flat", "HoldAll", "OneIdentity"},
toString: func(this *Expression, form string) (bool, string) {
return ToStringInfix(this.Parts[1:], " && ", form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringInfix(this.Parts[1:], " && ", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
res := NewExpression([]Ex{&Symbol{"System`And"}})
Expand Down Expand Up @@ -50,8 +50,8 @@ func GetBooleanDefinitions() (defs []Definition) {
Name: "Or",
Usage: "`e1 || e2 || ...` returns `True` if any expressions evaluate to `True`.",
Attributes: []string{"Flat", "HoldAll", "OneIdentity"},
toString: func(this *Expression, form string) (bool, string) {
return ToStringInfix(this.Parts[1:], " || ", form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringInfix(this.Parts[1:], " || ", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
res := NewExpression([]Ex{&Symbol{"System`Or"}})
Expand Down
32 changes: 16 additions & 16 deletions expreduce/builtin_comparison.go
Expand Up @@ -7,8 +7,8 @@ func getComparisonDefinitions() (defs []Definition) {
defs = append(defs, Definition{
Name: "Equal",
Usage: "`lhs == rhs` evaluates to True or False if equality or inequality is known.",
toString: func(this *Expression, form string) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " == ", true, "", "", form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " == ", true, "", "", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
if len(this.Parts) < 1 {
Expand Down Expand Up @@ -104,8 +104,8 @@ func getComparisonDefinitions() (defs []Definition) {
defs = append(defs, Definition{
Name: "Unequal",
Usage: "`lhs != rhs` evaluates to True if inequality is known or False if equality is known.",
toString: func(this *Expression, form string) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " != ", true, "", "", form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " != ", true, "", "", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
if len(this.Parts) != 3 {
Expand Down Expand Up @@ -143,8 +143,8 @@ func getComparisonDefinitions() (defs []Definition) {
defs = append(defs, Definition{
Name: "SameQ",
Usage: "`lhs === rhs` evaluates to True if `lhs` and `rhs` are identical after evaluation, False otherwise.",
toString: func(this *Expression, form string) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " === ", true, "", "", form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " === ", true, "", "", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
if len(this.Parts) < 1 {
Expand Down Expand Up @@ -210,8 +210,8 @@ func getComparisonDefinitions() (defs []Definition) {
defs = append(defs, Definition{
Name: "UnsameQ",
Usage: "`lhs =!= rhs` evaluates to False if `lhs` and `rhs` are identical after evaluation, True otherwise.",
toString: func(this *Expression, form string) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " =!= ", true, "", "", form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " =!= ", true, "", "", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
if len(this.Parts) < 1 {
Expand Down Expand Up @@ -279,8 +279,8 @@ func getComparisonDefinitions() (defs []Definition) {
defs = append(defs, Definition{
Name: "Less",
Usage: "`a < b` returns True if `a` is less than `b`.",
toString: func(this *Expression, form string) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " < ", true, "", "", form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " < ", true, "", "", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
if len(this.Parts) != 3 {
Expand All @@ -306,8 +306,8 @@ func getComparisonDefinitions() (defs []Definition) {
defs = append(defs, Definition{
Name: "Greater",
Usage: "`a > b` returns True if `a` is greater than `b`.",
toString: func(this *Expression, form string) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " > ", true, "", "", form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " > ", true, "", "", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
if len(this.Parts) != 3 {
Expand All @@ -333,8 +333,8 @@ func getComparisonDefinitions() (defs []Definition) {
defs = append(defs, Definition{
Name: "LessEqual",
Usage: "`a <= b` returns True if `a` is less than or equal to `b`.",
toString: func(this *Expression, form string) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " <= ", true, "", "", form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " <= ", true, "", "", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
if len(this.Parts) != 3 {
Expand Down Expand Up @@ -364,8 +364,8 @@ func getComparisonDefinitions() (defs []Definition) {
defs = append(defs, Definition{
Name: "GreaterEqual",
Usage: "`a >= b` returns True if `a` is greater than or equal to `b`.",
toString: func(this *Expression, form string) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " >= ", true, "", "", form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], " >= ", true, "", "", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
if len(this.Parts) != 3 {
Expand Down
4 changes: 2 additions & 2 deletions expreduce/builtin_expression.go
Expand Up @@ -177,14 +177,14 @@ func GetExpressionDefinitions() (defs []Definition) {
Name: "HoldForm",
Usage: "`HoldForm[expr]` prevents automatic evaluation of `expr`. Prints as `expr`.",
Attributes: []string{"HoldAll"},
toString: func(this *Expression, form string) (bool, string) {
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
if len(this.Parts) != 2 {
return false, ""
}
if form == "FullForm" {
return false, ""
}
return true, this.Parts[1].StringForm(form)
return true, this.Parts[1].StringForm(form, context, contextPath)
},
SimpleExamples: []TestInstruction{
&StringTest{"5^3", "HoldForm[Power[5, 3]]"},
Expand Down
2 changes: 1 addition & 1 deletion expreduce/builtin_list.go
Expand Up @@ -4,7 +4,7 @@ import "bytes"
import "math/big"
import "sort"

func (this *Expression) ToStringList(form string) (bool, string) {
func (this *Expression) ToStringList(form string, context *String, contextPath *Expression) (bool, string) {
if form == "FullForm" {
return false, ""
}
Expand Down
24 changes: 12 additions & 12 deletions expreduce/builtin_pattern.go
Expand Up @@ -2,7 +2,7 @@ package expreduce

import "bytes"

func ToStringBlankType(repr string, parts []Ex, form string) (bool, string) {
func ToStringBlankType(repr string, parts []Ex, form string, context *String, contextPath *Expression) (bool, string) {
if form == "FullForm" {
return false, ""
}
Expand Down Expand Up @@ -107,7 +107,7 @@ func GetPatternDefinitions() (defs []Definition) {
Usage: "`name{BLANKFORM}` is equivalent to `Pattern[name, {BLANKFORM}]` and can be used in pattern matching to refer to the matched expression as `name`, where `{BLANKFORM}` is one of `{_, __, ___}`.\n\n" +
"`name{BLANKFORM}head` is equivalent to `Pattern[name, {BLANKFORM}head]` and can be used in pattern matching to refer to the matched expression as `name`, where `{BLANKFORM}` is one of `{_, __, ___}`.",
Attributes: []string{"HoldFirst"},
toString: func(this *Expression, form string) (bool, string) {
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
if len(this.Parts) != 3 {
return false, ""
}
Expand All @@ -119,13 +119,13 @@ func GetPatternDefinitions() (defs []Definition) {
_, bsOk := HeadAssertion(this.Parts[2], "BlankSequence")
_, bnsOk := HeadAssertion(this.Parts[2], "BlankNullSequence")
if blankOk || bsOk || bnsOk {
buffer.WriteString(this.Parts[1].StringForm(form))
buffer.WriteString(this.Parts[2].StringForm(form))
buffer.WriteString(this.Parts[1].StringForm(form, context, contextPath))
buffer.WriteString(this.Parts[2].StringForm(form, context, contextPath))
} else {
buffer.WriteString("(")
buffer.WriteString(this.Parts[1].StringForm(form))
buffer.WriteString(this.Parts[1].StringForm(form, context, contextPath))
buffer.WriteString(") : (")
buffer.WriteString(this.Parts[2].StringForm(form))
buffer.WriteString(this.Parts[2].StringForm(form, context, contextPath))
buffer.WriteString(")")
}
return true, buffer.String()
Expand All @@ -149,8 +149,8 @@ func GetPatternDefinitions() (defs []Definition) {
Name: "Blank",
Usage: "`_` matches any expression.\n\n" +
"`_head` matches any expression with a `Head` of `head`.",
toString: func(this *Expression, form string) (bool, string) {
return ToStringBlankType("_", this.Parts, form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringBlankType("_", this.Parts, form, context, contextPath)
},
SimpleExamples: []TestInstruction{
&SameTest{"True", "MatchQ[a + b, _]"},
Expand Down Expand Up @@ -219,8 +219,8 @@ func GetPatternDefinitions() (defs []Definition) {
Name: "BlankSequence",
Usage: "`__` matches any sequence of one or more expressions.\n\n" +
"`__head` matches any sequence of one or more expressions, each with a `Head` of `head`.",
toString: func(this *Expression, form string) (bool, string) {
return ToStringBlankType("__", this.Parts, form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringBlankType("__", this.Parts, form, context, contextPath)
},
SimpleExamples: []TestInstruction{
&SameTest{"True", "MatchQ[a + b + c, a + b + __]"},
Expand Down Expand Up @@ -311,8 +311,8 @@ func GetPatternDefinitions() (defs []Definition) {
Name: "BlankNullSequence",
Usage: "`___` matches any sequence of zero or more expressions.\n\n" +
"`___head` matches any sequence of zero or more expressions, each with a `Head` of `head`.",
toString: func(this *Expression, form string) (bool, string) {
return ToStringBlankType("___", this.Parts, form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringBlankType("___", this.Parts, form, context, contextPath)
},
SimpleExamples: []TestInstruction{
&SameTest{"True", "MatchQ[a*b, ___]"},
Expand Down
4 changes: 2 additions & 2 deletions expreduce/builtin_power.go
Expand Up @@ -28,8 +28,8 @@ func GetPowerDefinitions() (defs []Definition) {
{"Power[Rational[a_,b_], -1]", "Rational[b,a]"},
{"Power[Rational[a_,b_], e_?Positive]", "Rational[a^e,b^e]"},
},
toString: func(this *Expression, form string) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], "^", false, "", "", form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringInfixAdvanced(this.Parts[1:], "^", false, "", "", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
if len(this.Parts) != 3 {
Expand Down
16 changes: 8 additions & 8 deletions expreduce/builtin_replacement.go
Expand Up @@ -30,11 +30,11 @@ func getReplacementDefinitions() (defs []Definition) {
Name: "ReplaceAll",
Usage: "`expr /. rule` replaces all occurences of the LHS of `rule` with the RHS of `rule` in `expr`.\n\n" +
"`expr /. {r1, r2, ...}` performes the same operation as `expr /. rule`, but evaluating each `r_n` in sequence.",
toString: func(this *Expression, form string) (bool, string) {
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
if len(this.Parts) != 3 {
return false, ""
}
return ToStringInfixAdvanced(this.Parts[1:], " /. ", true, "", "", form)
return ToStringInfixAdvanced(this.Parts[1:], " /. ", true, "", "", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
if len(this.Parts) != 3 {
Expand Down Expand Up @@ -242,11 +242,11 @@ func getReplacementDefinitions() (defs []Definition) {
Name: "ReplaceRepeated",
Usage: "`expr //. rule` replaces all occurences of the LHS of `rule` with the RHS of `rule` in `expr` repeatedly until the expression stabilizes.\n\n" +
"`expr //. {r1, r2, ...}` performes the same operation as `expr //. rule`, but evaluating each `r_n` in sequence.",
toString: func(this *Expression, form string) (bool, string) {
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
if len(this.Parts) != 3 {
return false, ""
}
return ToStringInfixAdvanced(this.Parts[1:], " //. ", true, "", "", form)
return ToStringInfixAdvanced(this.Parts[1:], " //. ", true, "", "", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
if len(this.Parts) != 3 {
Expand Down Expand Up @@ -281,11 +281,11 @@ func getReplacementDefinitions() (defs []Definition) {
Name: "Rule",
Usage: "`lhs -> rhs` can be used in replacement functions to say that instances of `lhs` should be replaced with `rhs`.",
Attributes: []string{"SequenceHold"},
toString: func(this *Expression, form string) (bool, string) {
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
if len(this.Parts) != 3 {
return false, ""
}
return ToStringInfixAdvanced(this.Parts[1:], " -> ", true, "", "", form)
return ToStringInfixAdvanced(this.Parts[1:], " -> ", true, "", "", form, context, contextPath)
},
SimpleExamples: []TestInstruction{
&SameTest{"2^(y+1) + y", "2^(x^2+1) + x^2 /. x^2 -> y"},
Expand All @@ -298,11 +298,11 @@ func getReplacementDefinitions() (defs []Definition) {
Name: "RuleDelayed",
Usage: "`lhs :> rhs` can be used in replacement functions to say that instances of `lhs` should be replaced with `rhs`, evaluating `rhs` only after replacement.",
Attributes: []string{"HoldRest", "SequenceHold"},
toString: func(this *Expression, form string) (bool, string) {
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
if len(this.Parts) != 3 {
return false, ""
}
return ToStringInfixAdvanced(this.Parts[1:], " :> ", true, "", "", form)
return ToStringInfixAdvanced(this.Parts[1:], " :> ", true, "", "", form, context, contextPath)
},
SimpleExamples: []TestInstruction{
&SameTest{"2^(y+1) + y", "2^(x^2+1) + x^2 /. x^2 :> y"},
Expand Down
7 changes: 4 additions & 3 deletions expreduce/builtin_string.go
Expand Up @@ -23,7 +23,8 @@ func GetStringDefinitions() (defs []Definition) {
return this
}

return &String{this.Parts[1].StringForm(formAsSymbol.Name[7:])}
context, contextPath := ActualStringFormArgs(es)
return &String{this.Parts[1].StringForm(formAsSymbol.Name[7:], context, contextPath)}
},
SimpleExamples: []TestInstruction{
&SameTest{"\"a^2\"", "ToString[a^2, InputForm]"},
Expand All @@ -42,8 +43,8 @@ func GetStringDefinitions() (defs []Definition) {
// OrderlessIsMatchQ
{"StringJoin[list_List]", "StringJoin[list /. List->Sequence]"},
},
toString: func(this *Expression, form string) (bool, string) {
return ToStringInfix(this.Parts[1:], " <> ", form)
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
return ToStringInfix(this.Parts[1:], " <> ", form, context, contextPath)
},
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
toReturn := ""
Expand Down
8 changes: 4 additions & 4 deletions expreduce/builtin_system.go
Expand Up @@ -219,11 +219,11 @@ func GetSystemDefinitions() (defs []Definition) {
Name: "Set",
Usage: "`lhs = rhs` sets `lhs` to stand for `rhs`.",
Attributes: []string{"HoldFirst", "SequenceHold"},
toString: func(this *Expression, form string) (bool, string) {
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
if len(this.Parts) != 3 {
return false, ""
}
return ToStringInfixAdvanced(this.Parts[1:], " = ", true, "(", ")", form)
return ToStringInfixAdvanced(this.Parts[1:], " = ", true, "(", ")", form, context, contextPath)
},
Bootstrap: true,
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
Expand Down Expand Up @@ -265,11 +265,11 @@ func GetSystemDefinitions() (defs []Definition) {
Name: "SetDelayed",
Usage: "`lhs := rhs` sets `lhs` to stand for `rhs`, with `rhs` not being evaluated until it is referenced by `lhs`.",
Attributes: []string{"HoldAll", "SequenceHold"},
toString: func(this *Expression, form string) (bool, string) {
toString: func(this *Expression, form string, context *String, contextPath *Expression) (bool, string) {
if len(this.Parts) != 3 {
return false, ""
}
return ToStringInfixAdvanced(this.Parts[1:], " := ", true, "(", ")", form)
return ToStringInfixAdvanced(this.Parts[1:], " := ", true, "(", ")", form, context, contextPath)
},
Bootstrap: true,
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
Expand Down

0 comments on commit a43cf34

Please sign in to comment.