Skip to main content

sim_lib_lang_scheme/
codec.rs

1use std::sync::Arc;
2
3use sim_codec::{
4    CodecDefaultDecode, CodecRuntime, Decoder, Input, LocatedDecoder, ReadCx, TreeDecoder,
5    codec_value,
6};
7use sim_kernel::{
8    AbiVersion, CodecId, DefaultFactory, Dependency, Export, Lib, LibManifest, LibTarget, Linker,
9    LocatedExpr, LocatedExprTree, Result, Symbol, Version,
10};
11
12use crate::{decode_scheme_tree, scheme_reader_symbol};
13
14/// Decoder turning Scheme surface text into the shared `Expr` graph.
15///
16/// Implements the kernel [`Decoder`], [`LocatedDecoder`], and [`TreeDecoder`]
17/// contracts; this profile supplies no encoder.
18pub struct SchemeCodec;
19
20impl Decoder for SchemeCodec {
21    fn decode(&self, cx: &mut ReadCx<'_>, input: Input) -> Result<sim_kernel::Expr> {
22        decode_scheme_tree(cx, "scheme", input).map(|tree| tree.expr)
23    }
24}
25
26impl LocatedDecoder for SchemeCodec {
27    fn decode_located(
28        &self,
29        cx: &mut ReadCx<'_>,
30        input: Input,
31        source_id: String,
32    ) -> Result<LocatedExpr> {
33        decode_scheme_tree(cx, source_id, input).map(|tree| tree.located())
34    }
35}
36
37impl TreeDecoder for SchemeCodec {
38    fn decode_tree(
39        &self,
40        cx: &mut ReadCx<'_>,
41        input: Input,
42        source_id: String,
43    ) -> Result<LocatedExprTree> {
44        decode_scheme_tree(cx, source_id, input)
45    }
46}
47
48/// Loadable [`Lib`] that registers [`SchemeCodec`] as a runtime codec.
49pub struct SchemeCodecLib {
50    symbol: Symbol,
51    codec_id: CodecId,
52}
53
54impl SchemeCodecLib {
55    /// Builds the codec lib bound to the given runtime [`CodecId`].
56    pub fn new(id: CodecId) -> Self {
57        Self {
58            symbol: scheme_reader_symbol(),
59            codec_id: id,
60        }
61    }
62}
63
64impl Lib for SchemeCodecLib {
65    fn manifest(&self) -> LibManifest {
66        LibManifest {
67            id: self.symbol.clone(),
68            version: Version(env!("CARGO_PKG_VERSION").to_owned()),
69            abi: AbiVersion { major: 0, minor: 1 },
70            target: LibTarget::HostRegistered,
71            requires: Vec::<Dependency>::new(),
72            capabilities: Vec::new(),
73            exports: vec![Export::Codec {
74                symbol: self.symbol.clone(),
75                codec_id: Some(self.codec_id),
76            }],
77        }
78    }
79
80    fn load(&self, _cx: &mut sim_kernel::LoadCx, linker: &mut Linker<'_>) -> Result<()> {
81        let _factory = DefaultFactory;
82        let expr_shape = sim_codec::resolve_expr_shape(linker, &Symbol::qualified("core", "Expr"))?;
83        let options_shape = sim_codec::resolve_options_shape(linker)?;
84
85        linker.codec_value(
86            self.symbol.clone(),
87            codec_value(CodecRuntime {
88                id: self.codec_id,
89                symbol: self.symbol.clone(),
90                decoder: Some(Arc::new(SchemeCodec)),
91                located_decoder: Some(Arc::new(SchemeCodec)),
92                tree_decoder: Some(Arc::new(SchemeCodec)),
93                encoder: None,
94                located_encoder: None,
95                tree_encoder: None,
96                expr_shape,
97                options_shape,
98                default_decode: CodecDefaultDecode::TermInEvalDatumOtherwise,
99            }),
100        )?;
101        Ok(())
102    }
103}