From 7b51fd59db6714d05ab8d5c1e728ff436a09fde7 Mon Sep 17 00:00:00 2001 From: Nicolas Boulenguez Date: Sun, 13 Oct 2024 20:17:55 +0200 Subject: [PATCH] vala: prevent defmacro! from mutating its argument --- impls/vala/step8_macros.vala | 22 +++++++++++++++++----- impls/vala/step9_try.vala | 22 +++++++++++++++++----- impls/vala/stepA_mal.vala | 22 +++++++++++++++++----- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/impls/vala/step8_macros.vala b/impls/vala/step8_macros.vala index 8d63a6501f..4b15ec8da5 100644 --- a/impls/vala/step8_macros.vala +++ b/impls/vala/step8_macros.vala @@ -172,14 +172,26 @@ class Mal.Main : GLib.Object { var sym = first as Mal.Sym; switch (sym.v) { case "def!": - case "defmacro!": if (list.length() != 3) throw new Mal.Error.BAD_PARAMS( "def!: expected two values"); - var val = define_eval(list.next.data, list.next.next.data, env); - if (sym.v == "defmacro!" && val is Mal.Function) { - (val as Mal.Function).is_macro = true; - } + return define_eval(list.next.data, list.next.next.data, + env); + case "defmacro!": + if (list.length() != 3) + throw new Mal.Error.BAD_PARAMS( + "defmacro!: expected two values"); + var symkey = list.next.data as Mal.Sym; + if (symkey == null) + throw new Mal.Error.BAD_PARAMS( + "defmacro!: expects a symbol"); + var val = EVAL(list.next.next.data, env) as Mal.Function; + if (val == null) + throw new Mal.Error.BAD_PARAMS( + "defmacro!: expected a function"); + val = val.copy(); + val.is_macro = true; + env.set(symkey, val); return val; case "let*": if (list.length() != 3) diff --git a/impls/vala/step9_try.vala b/impls/vala/step9_try.vala index d28831676b..3707e1e072 100644 --- a/impls/vala/step9_try.vala +++ b/impls/vala/step9_try.vala @@ -173,14 +173,26 @@ class Mal.Main : GLib.Object { var sym = first as Mal.Sym; switch (sym.v) { case "def!": - case "defmacro!": if (list.length() != 3) throw new Mal.Error.BAD_PARAMS( "def!: expected two values"); - var val = define_eval(list.next.data, list.next.next.data, env); - if (sym.v == "defmacro!" && val is Mal.Function) { - (val as Mal.Function).is_macro = true; - } + return define_eval(list.next.data, list.next.next.data, + env); + case "defmacro!": + if (list.length() != 3) + throw new Mal.Error.BAD_PARAMS( + "defmacro!: expected two values"); + var symkey = list.next.data as Mal.Sym; + if (symkey == null) + throw new Mal.Error.BAD_PARAMS( + "defmacro!: expects a symbol"); + var val = EVAL(list.next.next.data, env) as Mal.Function; + if (val == null) + throw new Mal.Error.BAD_PARAMS( + "defmacro!: expected a function"); + val = val.copy(); + val.is_macro = true; + env.set(symkey, val); return val; case "let*": if (list.length() != 3) diff --git a/impls/vala/stepA_mal.vala b/impls/vala/stepA_mal.vala index f7f5801a28..557455f932 100644 --- a/impls/vala/stepA_mal.vala +++ b/impls/vala/stepA_mal.vala @@ -173,14 +173,26 @@ class Mal.Main : GLib.Object { var sym = first as Mal.Sym; switch (sym.v) { case "def!": - case "defmacro!": if (list.length() != 3) throw new Mal.Error.BAD_PARAMS( "def!: expected two values"); - var val = define_eval(list.next.data, list.next.next.data, env); - if (sym.v == "defmacro!" && val is Mal.Function) { - (val as Mal.Function).is_macro = true; - } + return define_eval(list.next.data, list.next.next.data, + env); + case "defmacro!": + if (list.length() != 3) + throw new Mal.Error.BAD_PARAMS( + "defmacro!: expected two values"); + var symkey = list.next.data as Mal.Sym; + if (symkey == null) + throw new Mal.Error.BAD_PARAMS( + "defmacro!: expects a symbol"); + var val = EVAL(list.next.next.data, env) as Mal.Function; + if (val == null) + throw new Mal.Error.BAD_PARAMS( + "defmacro!: expected a function"); + val = val.copy(); + val.is_macro = true; + env.set(symkey, val); return val; case "let*": if (list.length() != 3)