V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
aligo
V2EX  ›  PHP

来造个php代码生成器吧,实在太难写了

  •  
  •   aligo · 2011-03-12 09:12:20 +08:00 · 11601 次点击
    这是一个创建于 4786 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我不是一个职业程序猿,觉得php实在太难写了,但同时php的性能还是可以的,而且最主要的是使用广泛
    之前帮sai姐姐写了一个算法,最近刨出来用scala和ruby重写了,可是她要我一定用php,坚决不在服务器上装jvm
    我看过(包括写过)一些php,它们其实不是代码而是密码,但是大多数情况下php就算不是最好的选择,也是唯一的选择
    这里应该有不少人对php是处于爱恨交织态度,所以既然逃不开在生产环境使用php,那么至少开发过程中可以不用写它吧
    于是我想了想,不如来做一个php代码生成器吧,以下是我结合使用php经历的构想,欢迎各位提意见:

    * 语法简化
    * 告别<?php ?>,纯净php代码,反正大家都会用模版,内嵌html是个糟糕的做法。php6也有此改进
    * 每一行末的;完全是必要的
    * 变量名的$号完全是没有必要,只要全局常量全大写,就不会混淆
    * 类名大驼峰,方法名小驼峰,为了一些语法糖不会混淆,这个必须强制

    * 类
    * 为了纯洁的oop,放弃static,改为类的伴生对象
    * 为了纯洁的oop,例如str_replace(...),改为str.replace(...),在字符串对象上调用方法。php6或者7也将如此
    * 类的访问控制如public private protected,应该像时髦的语言那样,尽可能少写。即默认public,一个private可以连续修饰好几个方法
    * 为了更好的oop,添加mixin功能。php6或者7也将如此
    * 基于上两条,同时提供更加细致的访问控制,可以用来专门指定对某个类及其后代的访问权限
    * 调用方法中的->改为.或空格,括号不是必须的
    * (2012)push->arr,如此实现从右到左调用方法,把2012插入数组arr后端,省略括号后为2012 push->arr

    * 方法
    * function -> def
    * 不变性原则,绝对不能传递引用
    * 无上限参数列表用*更直观,而不是在方法中func_get_args()
    * 可以有多个返回值


    * 静态类型
    我目测写php的时候一般至少有20%的单元测试代码不干别的,专门测试类型是否正确
    同上,还有更多(有时候是80%了)的phpdoc注释不干别的,专门标示方法参数的类型和返回值的类型
    所以静态类型虽然看上去很难用,但是有助于减少体力劳动,所以:
    * 语法:str1: String = "hello",用java们的空格方法显然太难看
    * 声明时,方法的输入输出一定要显式指定类型,但对于lamdba可选,因为它们大概不需要被单元测试和生成文档
    * 字面量和new方法创建对象,除非特例,否则显然不必要专门指定类型
    * SQL类型:我用php时,如要长距离传递SQL语句,会定义SQL类,然后执行SQL方法判断输入的类,一定得是SQL类才行。SQL类无法和字符串拼接,然后用bindParam输入参数,防止SQL注入和人为疏忽的SQL注入
    * 数组的成员类型要相同,即一个成员的key是数字那么该数组成员所有key都应该是数字,字符串"1"什么的是非法的
    * 隐式转换,有静态类型必然还要有它

    * 函数式编程
    虽然5.3开始支持了lamdba等,但是并不好用
    * 语法:{(arg1, arg2) ...},而不是function(arg1,arg2){...}
    * {(arg) ...}("foobar")的就地调用,结合前面的调用方法,("foobar"){(arg) ...}也可以,而且更美观
    * 结合纯洁的oop,arr.each{}用以代替foreach和变态for等循环语法,同时arr还应该有map和reduce/collect/folding等方法
    * 其他一些函数式方法似乎不是很必要

    * 其他
    * 让定义数组方法更像json些,用:而不是=>,用花括号而不是圆括号,array开头不是必须的

    以上基本是我目前的想法,非常不完整,大家有兴趣可以一起做这个东西,当然一切都是可以讨论的,目前我也只是设想阶段
    如果各位在哪里见过类似的东西,那就不需要重复发明轮子了XD
    52 条回复    2015-01-07 15:46:35 +08:00
    kayue
        1
    kayue  
       2011-03-12 09:30:29 +08:00
    從不用 template engine
    levn
        2
    levn  
       2011-03-12 09:39:52 +08:00
    看来发明一种方言是纠结的程序员的必然道路啊…… ==
    vayn
        3
    vayn  
       2011-03-12 10:28:14 +08:00
    第一眼看到这个题目想起 HipHop,但是仔细一想楼主其实是为了自己偷懒……比如 str_replace 改为 str.replace,问题是 PHP 根本就没有字串对象,这样改与其说是为了 OOP 不如说是为了满足自己的 OOP 心理,而且发明一种新的语言不是又要增加学习成本= =

    当然如果单纯为了自己方便,想怎样都可以啦,很好奇这个东东真正实现出来会是什么样子。

    另外我想知道伴生对象是什么……
    aligo
        4
    aligo  
    OP
       2011-03-12 10:41:00 +08:00
    @vayn 就是受到hiphop的启发,它刚出来那会我很有兴致地玩过了
    代码生成器当然也肯定就是为了偷懒而存在的,例如在接下来的php版本里肯定会变成str.replace之类的,只是我等不及了而已

    伴生对象类似于javascript中对象定义方法,一经声明就已经存在,伴生对象特殊之处在于:
    1、和类名同名,而且是大驼峰,永远不会和纯小写的对象变量混淆
    2、单例或者说静态,至于是不是实例化是无关紧要的问题了
    3、结合1和2,它对与他同名的类有平等互访权,所以可以用来做工厂方法

    例如:
    object User{
    def getById(id){
    ...
    new User(data)
    }
    }
    class User(data){
    def getName(){
    data[name]
    }
    }
    aligo
        5
    aligo  
    OP
       2011-03-12 10:44:57 +08:00
    使用起来:
    var user = User.getById(2012)
    echo user.getName //其实这是多余的,完全可以用getter嘛- -
    或者更酷的链式方法:
    echo User.getById(2012).getName
    aligo
        6
    aligo  
    OP
       2011-03-12 10:52:35 +08:00
    最主要的:
    可以在object User中定义
    ...
    protected def makeBaby(user_a,user_b){
    ...
    new User(data)
    }
    在class User中
    def makeLoveWith(user_b){
    if (...) {User.makeBaby(this,user_b)}
    }
    使用上
    baby = user1 makeLoveWith user2 || null //语法糖
    这样外部是访问不到User的makeBaby方法,避免感应受孕之类的情况发生
    vayn
        7
    vayn  
       2011-03-12 10:59:36 +08:00
    @aligo 我搜了一下,伴生对象看起来像是把静态成员和非静态成员分开,但是可以互访。我对 scala 也没概念,体会不到这样有什么好处。我喜欢关于“方法”和“函数式编程”的想法,PHP 在这方面还不够激进,按照楼主的想法来实现应该会很爽。不过“静态类型”对于一门弱类型语言来说是不是太过分了……
    aligo
        8
    aligo  
    OP
       2011-03-12 11:08:28 +08:00
    @vayn 没错,把逻辑代码分开,例如工厂方法之类显然不应该和类实例方法在一起
    静态类型的话其实只是伪静态,因为最后生成的php依然肯定是动态的,而这里指静态只是代码生成器运行时候进行的检验
    好处是在某些地方强调类型,可以避免很多不必要的错误,甚至安全问题,同时也可以少写很多注释和单元测试
    因为php经常需要从url接收信息,并且通过SQL操作数据库,如果实现伪静态类型至少避免很多低级疏忽
    reorx
        9
    reorx  
       2011-03-12 11:14:17 +08:00
    前提是选择一个与你的要求具有类似语法及表现形式的语言,然后基于这个语言做和PHP核心集成的framework。

    以前看到过类似的东西,希望对你有所启发:http://www.csh.rit.edu/~jon/projects/pip/

    这会有事,先mark,回头再想想~
    rechtar
        10
    rechtar  
       2011-03-12 11:14:23 +08:00
    我也一直觉得PHP的语法很丑很蛋疼 = =
    但是喂,这个想法更蛋疼一层啊!……

    题目写的太谦虚了。完全就是设计一门新的语言 + 写一个以PHP为目标的编译器了
    aligo
        11
    aligo  
    OP
       2011-03-12 11:20:14 +08:00
    @reorx 和那个有点不一样,并不是让php和其他语言一起工作

    就像@rechtar 说的一样,一门新语言,然后还有一个以php为目标的代码生成器
    vayn
        12
    vayn  
       2011-03-12 11:23:28 +08:00
    @aligo 牺牲灵活性来获得更高的安全吗,值得权衡一下。

    其实这样折腾一圈下来怎么都感觉有点别扭,不如直接用其他语言算了=。= 当然楼主是有特殊情况
    CupTools
        13
    CupTools  
       2011-03-12 11:27:16 +08:00
    一句话,不用PHP拉到。

    PHP的存在肯定有他自己的意义。如果你觉得PHP不爽,请慢走,PHP不是唯一的一种编程语言,你在YY也没用,PHP的基本语法是不会变的。
    aligo
        14
    aligo  
    OP
       2011-03-12 11:27:29 +08:00
    http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
    用php的人还是很多很多很多的,不过似乎比以前少了一点,被c#超过了
    然后静态类型不会带来什么灵活性问题吧,只是写代码的在某些地方多了声明类型的步骤,但同时与之相关的文档和测试工作可以省下更多
    cellsea
        15
    cellsea  
       2011-03-12 11:31:03 +08:00
    LZ,你可以去看看ActionScript 3, 真的,已经几乎实现了你的想法。。。。。
    reorx
        16
    reorx  
       2011-03-12 11:32:34 +08:00
    @aligo 之前也是这样想的,所以觉得使用已有的语言可能是更好的选择,毕竟是对PHP的语言规范不满么。如果发明新的语言,成本过高不说,也仅仅只是基于PHP语法的变种(似乎本质还是PHP),那么还不如直接改进PHP本身。再如果,这种新的语言,他的解释内核没有别的功能,只是生成对应的PHP代码,那么其实它不能被称作语言,而应该只是一种规范,就像json那样,最终的成果会是format + encoder&decoder。

    另外看你的设想,似乎有jQuery的影子诶……
    aligo
        17
    aligo  
    OP
       2011-03-12 11:37:19 +08:00
    @CupTools 这不是我一个人就能决定的事情
    另外php的语言在不断改变中,从php4到php5就变了不少,接下来也还会接着变的
    不过就现阶段考虑,我只能想到代码生成器这种土办法,我绝对不是在yy,例如java上的velocity就是把类似php的东西生成java代码
    aligo
        18
    aligo  
    OP
       2011-03-12 11:42:10 +08:00
    对头,不是一种新的语言,最后生成的还是php代码,所以实施起来比较简单
    这个初步设想的话,当然是山寨了各种语言的长处和各种实践经验,一切以好用方便为宗旨
    我是真打算做这个东西,因为php实在太难写了
    不知道有没有人想要一起来,让我自己做我很容易一条路走到黑然后坑掉
    vayn
        19
    vayn  
       2011-03-12 11:51:02 +08:00
    @aligo 我倒是很想陪你一起玩,只是不知道要怎么做呀
    CupTools
        20
    CupTools  
       2011-03-12 11:52:29 +08:00
    @aligo 一种语言不会因为你而改变,你要自己去适应。你觉得Java爽,那就JVM自己爽呗。假若一定要PHP,而你觉得PHP实在太恶心,让别人帮你恶心吧,免得苦了你自己
    aligo
        21
    aligo  
    OP
       2011-03-12 12:07:05 +08:00
    @CupTools 我不想改变php啊。。。另外也不觉得php恶心,只是写起来有点麻烦,而且缺乏表现力难以理解

    @vayn 没事,这事我也没干过,首先需要解析器和生成器,hiphop用的是Flex/Bison,不过我觉得用php写成的LIME更合适(http://sourceforge.net/projects/lime-php/),或者也可以用http://pear.php.net/package/PHP_ParserGenerator和http://pear.php.net/package/PHP_LexerGenerator
    然后再写一个标准库是必须的,没必要把所有特性,一股脑的交给生成器
    最后就是一些外围的工具,如make工具,和文档/单元测试工具的集成,编辑器的语法高亮等

    不过最重要的还是搞一个让大家满意而且愿意用的语法,当然这个可以慢慢改进

    有兴趣吗?
    darasion
        22
    darasion  
       2011-03-12 12:17:03 +08:00
    看来大家都这么想过啊!!!!!

    我从学php一开始,就想到这么做了。只是苦于没有时间精力更重要的是没有毅力!!!!!!

    许许多多的想法做法以及更重要的灵感都已经随着时间空间不经意间的逝去了!!!!!!

    后来一想好像似乎八成大概没准不一定这个东西应该没啥太大作用!!

    人们为啥总是想出很多很多很多生成某种语言的语言的语言的语言......

    始祖好像最先是01011010111吧啊!!!!!!!????????
    后来出了个什么汇编,它是不是生成01011010111语言的语言????
    再后来出什么A啊B啊C啊的语言,它好像大概是先生成汇编,然后再由汇编生成01011010111。是不是所谓搞基语言!????????

    后来后来是不是又有人在A啊B啊C啊的语言里边又创造出什么java、 c#、php等等乱七八糟的更搞基的语言!!!!!!!??????

    终于有一天!!!!我们来了,我们要做的是比更搞基语言更搞基的更更搞基语言!!!!

    未来的某一天,是不是有人觉得我们的更更搞基语言不够搞基,发明一个更更更搞基语言呢?????

    ............
    bcxx
        23
    bcxx  
       2011-03-12 12:28:49 +08:00
    @darasion 咆哮体了= =||

    其实每种语言都每种语言特点嘛,只不过php的语法实在是让人失望
    levn
        24
    levn  
       2011-03-12 12:38:17 +08:00
    原来机器语言是搞基语言…… — —
    rechtar
        25
    rechtar  
       2011-03-12 12:53:57 +08:00
    @aligo 解析器和生成器、外围工具、语法高亮,这些都不是大问题。只要肯把时间精力往里砸,几个月就能出来个样子了
    但是,「让大家满意而且愿意用的语法」——直说,这不可能的 = =

    @darasion 亮了!XD
    huangz
        26
    huangz  
       2011-03-12 13:37:24 +08:00
    见过一些有类似想法的人,不过都是做着做着就没有然后了。。。

    因为他们都转写python、ruby之类去了。
    harryxu
        27
    harryxu  
       2011-03-12 13:44:41 +08:00
    我感觉php虽然不是特别优雅,但也没有到神马丑陋的地步,配置好vim写起来也挺爽的。

    如果lz要找一个生成php代码的语言可以试试看看 haxe http://haxe.org/
    e6nian
        28
    e6nian  
       2011-03-12 13:47:39 +08:00
    囧。你想重复发明轮子么?
    写ruby或者node.js吧。
    reorx
        29
    reorx  
       2011-03-12 14:47:30 +08:00
    @huangz +1
    aligo
        30
    aligo  
    OP
       2011-03-12 15:25:01 +08:00
    @huangz python、ruby、groovy、scala、node.js、fantom、erlang、reia什么的时髦的语言,不敢说精通,我大概都折腾过一点吧(我不知道我这种折腾的态度对不对),然后又被迫回头
    现在php仍然是主流,我也没觉得php有多么糟糕,只是觉得写php应该更容易更轻松一些才是
    做着做着就没有然后了,这也是我担心的事情的XD
    @harryxu 恩,我了解haxe,准确的说我那些关于静态类型的想法就是来自于它,去掉$的想法就是来自于neko
    aligo
        31
    aligo  
    OP
       2011-03-12 16:00:43 +08:00
    天啊,我找到这个:
    http://code.google.com/p/php-snow/
    语法非常简洁,静态类型,内牛满面,至少和我的想法有80%的相似
    重新考虑是否要自己造一个。。。
    levn
        32
    levn  
       2011-03-12 16:26:14 +08:00
    为什么不考虑加入他们……
    aligo
        33
    aligo  
    OP
       2011-03-13 18:18:43 +08:00
    今天把php-snow看了一下,它用Python Lex-Yacc的解释器,还可以把现有的php转换回去
    虽然很多想法和我相似,但是感觉它精简过头了,例如用fn而不是def,用pri而不是print,不太符合日常期望,而且oop和fp也没有针对性改进
    est
        34
    est  
       2011-03-13 18:30:12 +08:00
    还不如基于zend什么的字节码搞个target compiling
    aligo
        35
    aligo  
    OP
       2011-03-13 18:34:42 +08:00
    @est 部署问题啊。。。
    如果那么搞的话,和直接编译成jvm或者bean或者neko或者像hiphop那样没区别了

    动机只是因为php太难写,而要代码生成器,生成的还是php
    aligo
        36
    aligo  
    OP
       2011-03-13 21:14:22 +08:00
    晚上把我对基本语法的想法写下来,欢迎吐槽

    一切都是对象和方法调用(类似Smalltalk),并且完全基于lambda(类似Lisp),实现各种语言的基本功能
    最简单例子1+1其实是1.+(1)
    包括代码块也是方法调用,所有代码其实都是一个顶层对象Source的内部调用
    如果创建一个类
    class A
    def a
    print "helloworld"
    其实是
    Source.class(A,{
    this.def(a,{
    print "helloworld"
    })
    })

    if(x == 0)
    ...
    else
    ...
    其实是
    this.if((x == 0),{...},{...})

    因此三目运算符
    (x == 0) ? 1 : 2
    其实是
    this.if((x == 0),1,2)

    调用方法的点是可选的,传递参数过程中圆括号可以省略,逗号可以用空格替代,花括号可以用换行缩进替代,end闭合代码块是可选的
    arr.each({...})
    str.replace("a","b")
    可以为
    arr each
    ...
    str replace "a" "b"

    lambda部分,具名输入为
    {(arg1,arg2,args*)
    ...
    }
    如果
    {
    print "helloworld"
    }
    print方法的调用对象,是上下文对象列表中的由最后一个到第一个中的一个,按顺序,第一个永远是Source
    所以对一个lambda对象执行call/apply方法
    lambda.apply(this) #定义上下文不调用方法
    lambda.call(...) #传入参数调用方法
    或者
    lambda(...)
    的输入参数永远是被加入到当前上下文对象列表中的最后一个
    基本上就是一个lambda会继承包裹自己的lambda的上下文对象列表,并且加入新的对象,再传递给自己内部的lambda
    用俗话说,就是类似闭包感觉,另外当然闭包也是存在的,唯一的区别就是不会在闭包能访问的对象上调用前面说到的print方法等

    简单说就是糅合各种语言,集大成的山寨语法
    另外我没把上面这些为什么这么做的好处写出来,要写估计又是一大堆了,有可能,我打算尽快着手实现
    aligo
        37
    aligo  
    OP
       2011-03-13 21:18:56 +08:00
    。。。贴出来之后缩进都被干掉了。。。
    大家自行脑补好了。。。

    现在实现上我最大难题就是eval,我只能想到提供一个php写的标准库然后把全部代码生成器的代码的都灌进去一遍的方法

    这就基本意味者这个php代码生成器必须用php写成(或者至少有php实现),而这东西诞生的目的是php很难写。。。

    另外php-snow用的PLY看上去是不错的,关键是一直被更新着
    aligo
        38
    aligo  
    OP
       2011-03-19 09:34:31 +08:00
    这两天稍微找了找能用的资源,并没有什么用来生成纯php解析器的生成器的好方案
    现在有的选择要么就是自己用php从头造一个,以后再慢慢改成用代码生成器生成(有点绕,就是用代码生成器生成自己的解析器生成器和代码生成器自己)
    要么像php-snow那样用例如PLY之类的
    各位有什么好主意吗。。。
    bigbrother
        39
    bigbrother  
       2011-03-19 09:48:26 +08:00
    我笑了,
    整天什么面向对象面向对象的,

    有几个是能按面向对象的编程标准写程序的,大多数时候,你们写个类跟写个方法没啥不同!
    ray58750034
        40
    ray58750034  
       2011-03-19 10:57:39 +08:00
    php-snow的语法有点看不懂了,用了太多自定义的东西。
    现在不是很时髦Polyglot Programming(多语言编程)么,相信慢慢地会有更多自定义的语言出现,计算机行业的进步啊~
    虽然我挺喜欢现在的php的,但还是很期待你的尝试。
    lychee
        41
    lychee  
       2011-03-28 12:34:21 +08:00
    = = 其实我觉得 当你用N年的时间做好这个东西 并且真的很好用
    但那时 云计算平台已经全面普及了 可以选择的语言相比现在丰富的多得多 这个东西一定会悲剧..
    ssword
        42
    ssword  
       2011-03-28 16:13:33 +08:00
    这已经是发明一门新的语言了,直觉上实现起来的成本该不小,而且php的虚拟机不一定都能提供支持。
    不过等楼主真正开始动手的时候,想法可能就有变化了吧
    aligo
        43
    aligo  
    OP
       2011-03-29 19:55:45 +08:00
    n年什么的就太那啥了
    另外还是以生成php代码为目标,并不需要考虑虚拟机之类的问题,会把一切东西都转换回php,最多就是依赖一个php写成的标准库
    另外我已经动手做了一部分,目前可以处理注释和简单的赋值表达式
    语法之类的也还没确定多少,做一步算一步,而且还没到可以作为一个项目存在的程度,大家要看可以私下找我
    而且因为不是很有时间,所以进展缓慢。。。
    yuxing1171
        44
    yuxing1171  
       2011-04-11 09:41:03 +08:00
    这个上面有什么好纠结的...
    ashchen
        45
    ashchen  
       2011-04-13 18:06:50 +08:00
    有类似想法,但做个可视化IDE更有实际价值

    把if ,while... 做成可视化的,那时候,转换成任何语言都方便
    msxcms
        46
    msxcms  
       2011-04-17 17:08:50 +08:00
    要按LZ的来……我就不会写PHP了
    mcfog
        47
    mcfog  
       2011-04-30 23:57:40 +08:00
    抄送条sai姐的推
    http://www.fructoselang.org/ 何等OO疼高科技,Ruby to PHP。』
    real_newbie
        48
    real_newbie  
       2011-05-01 00:22:37 +08:00
    可以嘛. JavaScript太难写, 不是搞出来了个CoffeeScript.
    aligo
        49
    aligo  
    OP
       2011-05-01 07:47:34 +08:00
    @mcfog -A-这有什么不好

    然后这东西我做了个开头,就放在一边了,等接下来放假有时间再继续
    reus
        50
    reus  
       2011-05-01 18:45:28 +08:00
    我也打算做这个,现在在补parsing的技术
    chuck911
        51
    chuck911  
       2011-05-01 20:28:05 +08:00
    每种流行语言都有它的独到之处,php的$和一堆函数str_*,array_*是有它的好处的。$带来的动态特性实现做很多有意思的功能。不同语言都有自己独有的生态环境,楼主显然就是不适应,建议先读点著名框架的源码,学满80小时再说它好不好。不过楼主真要想做这个新奇又酷的东西我绝对支持
    picasso250
        52
    picasso250  
       2015-01-07 15:46:35 +08:00
    当年我的想法和 @aligo 一样, 现在已经妥协了.
    @chuck911 我懂你的意思, 而且完全赞成.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3262 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 12:56 · PVG 20:56 · LAX 05:56 · JFK 08:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.