[refactor] Is this the functor/applicative/monadic life?
This is a big change. For chapter 5, I ripped out all line/column
tracking and most error handling from the parser; it's now a plain
ol' Lisp parser, and if it's not close to CL 22.1.1, it's a hell of
a lot closer than it used to be.
In doing so, I reduced the size of the parser by about 40 lines.
TrackingReader takes every function in a Reader and puts that
debugging information *back*. It turns out that all that information
was prelude and postlude to the act of parsing; by wrapping each
function in a decorator I was able to restore all that information,
and I only had to get it right exactly *once*.
In functional programming terms, this lifts:
IO -> (atom | list)
to:
IO with tracking -> Node (atom | list) with tracking
It's a totally free win without having to do much extra work.
Now, this check-in isn't perfect. The tracking reader is still
tossing on some things, and because I don't have a robust type
system (it is Coffeescript, after all), I'm having to do the
decorating and wrapping by hand. But I'm definitely on my way
to understanding the issues, and having a grasp on functors and
monoids.
2015-08-20 15:50:52 +00:00
|
|
|
{Reader, ReadError, Source} = require './reader'
|
|
|
|
{Node} = require './reader_types'
|
|
|
|
|
|
|
|
liftToTrack = (f) ->
|
|
|
|
(ioStream) ->
|
|
|
|
ioStream = if ioStream instanceof Source then ioStream else new Source ioStream
|
|
|
|
[line, column] = ioStream.position()
|
|
|
|
obj = f.apply(this, arguments)
|
|
|
|
if obj instanceof ReadError
|
|
|
|
obj['line'] = line
|
|
|
|
obj['column'] = column
|
|
|
|
return obj
|
|
|
|
if obj instanceof Node then obj else new Node obj, line, column
|
|
|
|
|
|
|
|
TrackingReader = class
|
2015-08-26 05:01:21 +00:00
|
|
|
|
[refactor] Is this the functor/applicative/monadic life?
This is a big change. For chapter 5, I ripped out all line/column
tracking and most error handling from the parser; it's now a plain
ol' Lisp parser, and if it's not close to CL 22.1.1, it's a hell of
a lot closer than it used to be.
In doing so, I reduced the size of the parser by about 40 lines.
TrackingReader takes every function in a Reader and puts that
debugging information *back*. It turns out that all that information
was prelude and postlude to the act of parsing; by wrapping each
function in a decorator I was able to restore all that information,
and I only had to get it right exactly *once*.
In functional programming terms, this lifts:
IO -> (atom | list)
to:
IO with tracking -> Node (atom | list) with tracking
It's a totally free win without having to do much extra work.
Now, this check-in isn't perfect. The tracking reader is still
tossing on some things, and because I don't have a robust type
system (it is Coffeescript, after all), I'm having to do the
decorating and wrapping by hand. But I'm definitely on my way
to understanding the issues, and having a grasp on functors and
monoids.
2015-08-20 15:50:52 +00:00
|
|
|
for own key, func of Reader::
|
|
|
|
TrackingReader::[key] = liftToTrack(func)
|
2015-08-26 05:01:21 +00:00
|
|
|
TrackingReader::acc = (obj) -> obj.v
|
[refactor] Is this the functor/applicative/monadic life?
This is a big change. For chapter 5, I ripped out all line/column
tracking and most error handling from the parser; it's now a plain
ol' Lisp parser, and if it's not close to CL 22.1.1, it's a hell of
a lot closer than it used to be.
In doing so, I reduced the size of the parser by about 40 lines.
TrackingReader takes every function in a Reader and puts that
debugging information *back*. It turns out that all that information
was prelude and postlude to the act of parsing; by wrapping each
function in a decorator I was able to restore all that information,
and I only had to get it right exactly *once*.
In functional programming terms, this lifts:
IO -> (atom | list)
to:
IO with tracking -> Node (atom | list) with tracking
It's a totally free win without having to do much extra work.
Now, this check-in isn't perfect. The tracking reader is still
tossing on some things, and because I don't have a robust type
system (it is Coffeescript, after all), I'm having to do the
decorating and wrapping by hand. But I'm definitely on my way
to understanding the issues, and having a grasp on functors and
monoids.
2015-08-20 15:50:52 +00:00
|
|
|
|
2015-08-26 05:01:21 +00:00
|
|
|
exports.ReadError = ReadError
|
[refactor] Is this the functor/applicative/monadic life?
This is a big change. For chapter 5, I ripped out all line/column
tracking and most error handling from the parser; it's now a plain
ol' Lisp parser, and if it's not close to CL 22.1.1, it's a hell of
a lot closer than it used to be.
In doing so, I reduced the size of the parser by about 40 lines.
TrackingReader takes every function in a Reader and puts that
debugging information *back*. It turns out that all that information
was prelude and postlude to the act of parsing; by wrapping each
function in a decorator I was able to restore all that information,
and I only had to get it right exactly *once*.
In functional programming terms, this lifts:
IO -> (atom | list)
to:
IO with tracking -> Node (atom | list) with tracking
It's a totally free win without having to do much extra work.
Now, this check-in isn't perfect. The tracking reader is still
tossing on some things, and because I don't have a robust type
system (it is Coffeescript, after all), I'm having to do the
decorating and wrapping by hand. But I'm definitely on my way
to understanding the issues, and having a grasp on functors and
monoids.
2015-08-20 15:50:52 +00:00
|
|
|
exports.Reader = TrackingReader
|
|
|
|
exports.reader = reader = new TrackingReader()
|
|
|
|
exports.read = -> reader.read.apply(reader, arguments)
|
2015-08-26 05:01:21 +00:00
|
|
|
|