From a3349f25369ff64bc256fbd5a3a896a5c7afc3ea Mon Sep 17 00:00:00 2001 From: Nicolas Boulenguez Date: Wed, 9 Oct 2024 19:41:32 +0200 Subject: [PATCH] crystal: prevent defmacro! from mutating its argument --- impls/crystal/step8_macros.cr | 4 +++- impls/crystal/step9_try.cr | 4 +++- impls/crystal/stepA_mal.cr | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/impls/crystal/step8_macros.cr b/impls/crystal/step8_macros.cr index 464b952867..2c7ac4e755 100755 --- a/impls/crystal/step8_macros.cr +++ b/impls/crystal/step8_macros.cr @@ -154,7 +154,9 @@ module Mal eval_error "wrong number of argument for 'defmacro!'" unless list.size == 3 a1 = list[1].unwrap eval_error "1st argument of 'defmacro!' must be symbol: #{a1}" unless a1.is_a? Mal::Symbol - return Mal::Type.new env.set(a1.str, eval(list[2], env).tap { |n| n.is_macro = true }) + mac = eval(list[2], env).dup + mac.is_macro = true + return Mal::Type.new env.set(a1.str, mac) else evaluated_first = eval(list.first, env) f = evaluated_first.unwrap diff --git a/impls/crystal/step9_try.cr b/impls/crystal/step9_try.cr index 180073a95a..984158b28f 100755 --- a/impls/crystal/step9_try.cr +++ b/impls/crystal/step9_try.cr @@ -154,7 +154,9 @@ module Mal eval_error "wrong number of argument for 'defmacro!'" unless list.size == 3 a1 = list[1].unwrap eval_error "1st argument of 'defmacro!' must be symbol: #{a1}" unless a1.is_a? Mal::Symbol - return Mal::Type.new env.set(a1.str, eval(list[2], env).tap { |n| n.is_macro = true }) + mac = eval(list[2], env).dup + mac.is_macro = true + return Mal::Type.new env.set(a1.str, mac) when "try*" catch_list = list.size >= 3 ? list[2].unwrap : Mal::Type.new(nil) return eval(list[1], env) unless catch_list.is_a? Mal::List diff --git a/impls/crystal/stepA_mal.cr b/impls/crystal/stepA_mal.cr index dba243a052..2857c89d13 100755 --- a/impls/crystal/stepA_mal.cr +++ b/impls/crystal/stepA_mal.cr @@ -160,7 +160,9 @@ module Mal eval_error "wrong number of argument for 'defmacro!'" unless list.size == 3 a1 = list[1].unwrap eval_error "1st argument of 'defmacro!' must be symbol: #{a1}" unless a1.is_a? Mal::Symbol - return Mal::Type.new env.set(a1.str, eval(list[2], env).tap { |n| n.is_macro = true }) + mac = eval(list[2], env).dup + mac.is_macro = true + return Mal::Type.new env.set(a1.str, mac) when "try*" catch_list = list.size >= 3 ? list[2].unwrap : Mal::Type.new(nil) return eval(list[1], env) unless catch_list.is_a? Mal::List