关于“everything is an expression”……

上午写的东西太乱了,还是重新理一下吧:

之前我在思考回归C89标准,也就是放弃所有C的新特性编程,但发现还是缺了点什么。C89里面的statement有六种类型:

statement
	: labeled_statement
	| compound_statement
	| expression_statement
	| selection_statement
	| iteration_statement
	| jump_statement
	;

然后这里面只有两个分支能从不含statement的句子归约到statement,一个是expression_statement,另一个是compound_statement(又叫做block)。

expression_statement
	: ';'
	| expression ';'
	;

compound_statement
	: '{' '}'
	| '{' statement_list '}'
	| '{' declaration_list '}'
	| '{' declaration_list statement_list '}'
	;

也就是说,能归约到statement的不含statement的句子,要么是{ declaration_list },要么是expression;,没别的了。而declaration不产生副作用,在C89里面甚至不参与运行时。所以,所有的求值,最后都来自于expression。而C89里面的expression只有一种子类型,assignment_expression

LdBeth关注的应该是对编译优化的影响,从语义上说,statement顺序应当决定IO顺序,但是,因为statement推导,而一个statement中诸expression应该何时被求值,是不受statement约束,也不应该受statement约束的。理想的状态应该是:每个statement都遵循时序,statement里的每个expression都能在语义上遵循约定的求值顺序。

assignment_expression的设计固然有蠢的好处,早期的芯片上,所有涉及io的指令,基本都是单指令流单数据的mov指令。但是现在的芯片就不太一样了。C目前也做了多发射和向量化SIMD的优化,那是建立在打乱既定的expression求值顺序的前提下的。这种优化在语义上对用户不透明,只能借助额外的、非语义上的同步机制。

我当时比较关注的是block不能参与assignment_expression的右值,在C89里面作为右值的必须是引用或者常量,{ initializer_list }不是expression,而且只能参与declaration。在C20里面,它是可以做右值的,但依然不是完整的block。我当时考虑的是一种允许以block为右值的C,block作为值而不是statement处理。

至于正确的设计是什么,我真的也不知道。

1 个赞