This document describes the implementation of the output_style option for the Starlog library, which allows users to convert between nested function call syntax and method chaining syntax when outputting Starlog code.
Add output_style(nested_calls) or output_style(method_chaining) options to starlog_to_prolog_file() and starlog_output_code().
Implemented the output_style option for starlog_output_code/3 and starlog_output_file/3 with two transformation modes:
Converts method chains (using >> operator) to nested function calls.
Example:
Input: X is reverse([1,2,3]) >> length
Output: X is length(reverse([1,2,3]))Usage:
?- starlog_output_code(
(X is reverse([1,2,3]) >> length),
Code,
[output_style(nested_calls), print(true)]
).
% Outputs: A is length(reverse([1,2,3]))Converts nested function calls to method chains.
Example:
Input: X is length(reverse([1,2,3]))
Output: X is reverse([1,2,3]) >> lengthUsage:
?- starlog_output_code(
(X is length(reverse([1,2,3]))),
Code,
[output_style(method_chaining), print(true)]
).
% Outputs: A is reverse([1,2,3])>>lengthThe implementation handles multiple levels of nesting/chaining:
% Chain to nested
Input: X is sort([3,1,2]) >> reverse >> length
Output: X is length(reverse(sort([3,1,2])))
% Nested to chain
Input: X is length(reverse(sort([3,1,2])))
Output: X is sort([3,1,2]) >> reverse >> lengthWorks with Starlog operators (:, &, •):
% List append as chain base
Input: X is ([1,2]&[3,4]) >> reverse >> length
Output: X is length(reverse([1,2]&[3,4]))
% Extract operator base when converting to chain
Input: X is length(reverse([1,2]&[3,4]))
Output: X is [1,2]&[3,4] >> reverse >> lengthTransformations are reversible:
Original: X is reverse([1,2,3]) >> length
→ Nested: X is length(reverse([1,2,3]))
→ Chain: X is reverse([1,2,3]) >> lengthThe output_style option works seamlessly with other options:
% With compression
?- starlog_output_code(
(string_concat("a", "b", T1), string_concat(T1, "c", T2)),
Code,
[compress(true), output_style(method_chaining), print(true)]
).
% Outputs: A is "a":"b":"c"
% With variable renaming
?- starlog_output_code(
(X is reverse([1,2,3]) >> length),
Code,
[output_style(nested_calls), rename(true), print(true)]
).
% Outputs: A is length(reverse([1,2,3]))-
apply_output_style/3: Main dispatcher for style transformations
apply_output_style(+Code, +Style, -TransformedCode)
-
transform_chains_to_nested/2: Converts method chains to nested calls
transform_chains_to_nested(+Code, -NestedCode)
-
transform_nested_to_chains/2: Converts nested calls to method chains
transform_nested_to_chains(+Code, -ChainCode)
- Detect method chain expressions (
Base >> Method1 >> Method2 >> ...) - Collect all methods in the chain into a list
- Build nested calls from inside out:
MethodN(...Method2(Method1(Base))...)
- Detect nested function calls where the last argument is another function
- Recursively extract the innermost expression as the base
- Build chain from base outward:
Base >> Method1 >> Method2 >> ... - Handle operator expressions as chain bases
- Single function calls (no transformation needed)
- Simple values without functions (pass through)
- Operator expressions as function arguments
- Mixed nested and operator expressions
- Functions with multiple arguments
starlog_output_code(+Goal, -StarlogCode, +Options)Options:
output_style(nested_calls)- Convert method chains to nested callsoutput_style(method_chaining)- Convert nested calls to method chains- Other options:
compress(true/false),print(true/false),rename(true/false), etc.
starlog_output_file(+FilePath, +OutputStream, +Options)Options:
output_style(nested_calls)- Convert method chains to nested callsoutput_style(method_chaining)- Convert nested calls to method chains- Other options:
compress(true/false), etc.
Created comprehensive test suite in tests/test_output_style.pl:
- 19 tests covering all transformation scenarios
- All tests passing
- Tests include:
- Basic transformations
- Multi-level transformations
- Operator expressions
- Edge cases
- Idempotence tests
- Complex combinations
Created demonstration file demo_output_style.pl showing:
- Basic transformations
- Multi-level transformations
- Integration with Starlog operators
- Roundtrip conversions
- Combination with other options
- File operations
?- use_module(starlog).
% Convert chain to nested
?- starlog_output_code(
(X is reverse([1,2,3]) >> length),
Code,
[output_style(nested_calls)]
).
Code = (_ is length(reverse([1,2,3]))).
% Convert nested to chain
?- starlog_output_code(
(X is length(reverse([1,2,3]))),
Code,
[output_style(method_chaining)]
).
Code = (_ is reverse([1,2,3])>>length).% Convert a Starlog file to show code in nested style
?- starlog_output_file(
'my_code.pl',
user_output,
[output_style(nested_calls)]
).
% Convert a Starlog file to show code in chaining style
?- starlog_output_file(
'my_code.pl',
user_output,
[output_style(method_chaining)]
).% Compress and convert to chain style
?- starlog_output_code(
(string_concat("a", "b", T1), string_concat(T1, "c", T2)),
Code,
[compress(true), output_style(method_chaining), print(true)]
).
% Outputs: A is "a":"b":"c"- Readability: Choose the style that's most readable for your use case
- Flexibility: Convert between styles as needed
- Compatibility: Works with all existing Starlog features
- Reversibility: Transformations preserve semantics
- Integration: Seamless integration with other options
-
starlog.pl
- Added
apply_output_style/3predicate - Added transformation predicates
- Updated
starlog_output_code/3 - Updated
starlog_output_file/3 - Added helper predicates for conversion
- Added
-
tests/test_output_style.pl (new)
- Comprehensive test suite
- 19 tests covering all scenarios
-
demo_output_style.pl (new)
- Comprehensive demonstration
- Shows all features and use cases
All changes are backward compatible:
- Existing code works without modification
- The
output_styleoption is optional - Default behavior unchanged when option not specified
- All existing tests pass
Potential future improvements:
- Support for custom style preferences
- Automatic style detection
- Style consistency checking
- Integration with IDE/editor tools