-
-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
how much work needed to make it work at compile time? #70
Comments
The lexer can handle different sources (strings, streams) with the Since the VM cannot cast, this code needs to be refactored in some way. The idea of However, there is no guarantee that the rest of the code will work at compile-time. |
This feature is crucial for nimitai so I plan to tackle it soon. |
@sealmove There are two other issues related to the current state of the lexer, #85 (also some more information available there) and several failures to comply to the YAML specification which are not documented as GitHub issue but available in this list of skipped tests (the tests come from the official YAML test suite). The best way to go ahead is to rewrite the Lexer properly. I basically know how to do it since I wrote AdaYaml after NimYAML and avoided all these issues there. Since this and the other issue seem to be important, I will try and accomplish a rewrite till the end of the month, to avoid putting more effort into code that cannot be fixed to solve all its issues without rewriting it (a change is needed in how the input is tokenized). Would this work for you? I can't really guarantee that a Lexer rewrite will completely fix this issue but you can take it up from there. |
@flyx Sorry I didn't notice your reply until now. This is awesome news!
Yes, absolutely. Please notify me when the new lexer is ready. |
@sealmove Status update: The rewrite is mostly working (as seen in the branch Compile time execution is currently blocked by the global usage of A quick downgrading edit shows that NimYAML indeed works at compiletime when this obstacle is removed. Work on the branch should be finished soon™. |
The lexer rewrite has now landed in the The following code using NimYAML at compile time now compiles and yields the expected result: import yaml
type
Person = object
firstnamechar: char
surname: string
age: int32
setTagUri(Person, "!person")
const persons = loadAs[seq[Person]]("""
- {firstnamechar: K, surname: Koch, age: 23}
- {firstnamechar: S, surname: McDuck, age: 150}""")
for p in persons:
echo p However, latest Nim head is required for this to work. Nim 1.4.0 fails to do it because Currently not working are I invite everyone taking interest in this issue to test their use-case with NimYAML's current |
@flyx this snippet gives: EDIT: looks like i was on master, not devel; why is the main branch called devel instead of master? this goes against virtually all github repos and nimble packages (with the only exception of nim repo itself) ? (this aside, this is great news, thanks!) |
I don't understand this part; it prevents a lot of usage at CT even with nim-lang/Nim#15528; why are pointer needed for that? |
The master branch is for releases; a checkout of master will give you the latest release. This is common workflow for larger projects although I admit that most single-dev repos don't use it; it's just my preferred workflow. It should not really matter since
To resolve aliases. For example: import yaml
type
Node = ref object
name: string
children: seq[Node]
let input = """
name: root
children:
- &a
name: A
children: []
- name: B
children: [*a]
"""
let root = loadAs[Node](input)
echo root.children[0].name # will be A
echo root.children[1].children[0].name # will be the same A NimYAML will create multiple references to I am not sure what the alternative to this would be. I guess it would be possible to have one hashmap per type but that would involve lots of macro magic to generate the necessary amount of hashmaps based on the type we deserialize to (it would need to collect all In OOP languages like Java I would use the base Perhaps anchors could simply be forbidden during compile time, but I'm not entirely sure how to do that. Is there some I am no active Nim user apart from maintaining this library so there may be options I am not familiar with. If you know one, please tell me. |
Thanks for this work!
Fyi yes, there is. |
At least nimyaml should allow to deal with ref types that don't involve multiple references to the same object, that's a very common use case.
I disagree with that; ref could be in the type declaration (eg to allow multiple references at run time) but not in the serialization string (ie no multiple references to same object mentioned in serialization string); it's common
why don't you use when true:
type Foo = ref object
x: int
proc main()=
let f1 = Foo(x: 10)
let b1 = cast[int](f1)
static: main()
main() the address (via EDIT: maybe the problem is you need the reverse direction as well, ie: |
Yes, without the reverse cast, it would not be possible to put the value together.
That would certainly be the best solution, compared with |
when true:
import yaml
type
Person = ref object
firstnamechar: char
surname: string
age: int32
proc `$`(a: Person): string = $a[]
setTagUri(Person, "!person")
proc fn =
let persons = loadAs[seq[Person]]("""
- {firstnamechar: K, surname: Koch, age: 23}
- {firstnamechar: S, surname: McDuck, age: 150}""")
echo persons
static: fn()
fn() CT:
|
Great work! Probably better test code is the one with nodes which actually uses anchors & aliases – the code you posted only assures the cast compiles but never uses it: import yaml
type
Node = ref object
name: string
children: seq[Node]
static:
let input = """
name: root
children:
- &a
name: A
children: []
- name: B
children: [*a]
"""
let root = loadAs[Node](input)
echo root.children[0].name
echo root.children[1].children[0].name |
can we re-open this issue until support at CT is reasonable (doesn't have to be complete for that)? your snippet doesn't work, but neither does the following that doesn't contain anchors: when true:
import yaml
type
Node = ref object
name: string
children: seq[Node]
proc main =
let input = """
name: root
children:
- name: A
children: []
"""
let root = loadAs[Node](input)
echo root.children[0].name
static: main()
main() gives:
with #89 it gives:
upon further investigating it looks like edit: see #91 for further analysis on this particular issue
|
Fair enough. I'll reopen the issue. The error in your code is unrelated to when true:
import yaml
proc main =
let input = """
name: root
children:
- name: A
children: []
"""
let p = initYamlParser(serializationTagLibrary)
let s = p.parse(input)
try:
while true:
let e = s.next()
echo e
if e.kind == yamlEndStream: break
except:
echo repr(getCurrentException())
static: main()
main() This runs into an exception at compile time but works at runtime. I'll investigate to pinpoint what goes wrong. |
can you show it? your snippet works for me, no exception raised, but prints different things at RT and CT:
at CT: at RT: |
With Nim 2.0.0 and current devel, RT and CT both work for the snippet I posted above. That leaves the ref-to-ptr-cast error the only known remaining issue for CT. |
after applying the patch from #69 (comment) to make it work with latest nim 0.20 (which does work!), I'm trying to make it work at compile time; currently it gives compiler errors for the basic examples in https://nimyaml.org/
newFileStream doesn't work at CT so I tried this as well:
which gives several errors eg:
Has anyone succeeded in making it work at CT (even with a more limited set of yaml features would be a start)?
The text was updated successfully, but these errors were encountered: